balena-io-library / resin-rpi-raspbian

Apache License 2.0
74 stars 27 forks source link

Docker's recommended way of modifying path with `ENV PATH /foo:$PATH` doesn't work with resin images #3

Closed sorccu closed 9 years ago

sorccu commented 9 years ago

I was trying to build an application based on resin/rpi-raspbian (and resin/armv7hf-debian) and found out that my sample Dockerfile:

FROM resin/rpi-raspbian:jessie-2015-08-05
ENV PATH /app/bin:$PATH

Would result in this error:

[root@alarmpi temp]# docker build -t pathtest . && docker run -ti --rm pathtest bash
Sending build context to Docker daemon 2.048 kB
Sending build context to Docker daemon
Step 0 : FROM resin/rpi-raspbian:jessie-2015-08-05
 ---> 6c85dc1dc385
Step 1 : ENV PATH /app/bin:$PATH
 ---> Using cache
 ---> 84731ec46cc5
Successfully built 84731ec46cc5
exec: "bash": executable file not found in $PATH
Error response from daemon: Cannot start container 21cb1e224fbca66f232d1bcfc132966df3fbf45faa9b90a8fcdef921b945c4e8: [8] System error: exec: "bash": executable file not found in $PATH

This was very confusing but I figured out the cause. First, here's an example of how it's actually supposed to work (from my MBP):

FROM ubuntu:14.04
ENV PATH /app/bin:$PATH
➜  foo  docker build -t pathtest . && docker run -ti --rm pathtest bash
Sending build context to Docker daemon 2.048 kB
Sending build context to Docker daemon
Step 0 : FROM ubuntu:14.04
 ---> 8251da35e7a7
Step 1 : ENV PATH /app/bin:$PATH
 ---> Using cache
 ---> 84aa7b3f2b6b
Successfully built 84aa7b3f2b6b
root@fb52c1f6e6cf:/#

The problem is commit 9cde84cabeca4114fbeb740edce2740caae892e8 that set LC_ALL=C.UTF-8 by default.

Here's how Docker knows how to fetch the initial value for $PATH:

  1. There's a hardcoded default path in daemon/container_unix.go#L40
  2. When processing FROM, Docker appends the default $PATH to the environment ONLY IF the base image doesn't set any ENV by itself, in builder/internals.go#L536

Indeed, if we check the base image config values, we can see the difference:

➜  foo  docker inspect ubuntu:14.04 | jq '.[].Config.Env'
null
[root@alarmpi temp]# docker inspect resin/rpi-raspbian:jessie-2015-08-05 | jq '.[].Config.Env'
[
  "LC_ALL=C.UTF-8"
]

So, because the resin base images have a non-empty Env, the default $PATH never gets added to the list, and hence my problem.

Setting the $PATH like I'm doing is mentioned in Best practices for writing Dockerfiles, so I don't think I'm the only one with this problem.

And just to further confirm the cause, the issue doesn't occur with your older images like resin/rpi-raspbian:wheezy-2015-06-17:

[root@alarmpi temp]# docker build -t pathtest . && docker run -ti --rm pathtest bash
Sending build context to Docker daemon 2.048 kB
Sending build context to Docker daemon
Step 0 : FROM resin/rpi-raspbian:wheezy-2015-06-17
 ---> cbcadcbfd9a3
Step 1 : ENV PATH /app/bin:$PATH
 ---> Running in 4ec6337818d9
 ---> 8d4921c7d38c
Removing intermediate container 4ec6337818d9
Successfully built 8d4921c7d38c
root@d6c146466dbd:/#

Can we get this fixed?

nghiant2710 commented 9 years ago

@sorccu Thanks for the report. We have a PR for this: https://github.com/resin-io-library/resin-rpi-raspbian/pull/4 and will get this fixed soon. Happy hacking with Resin!