-
Notifications
You must be signed in to change notification settings - Fork 847
Description
Background:
Stack's Docker support initializes the PATH in the container using the container's default PATH, taken apparently from docker inspect. That relies on the unenforced best practice of setting a reasonable PATH in the Dockerfile:
https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#/env
@dysinger just tried using stack on an image that doesn't follow this best practice (he said he generated the image via packer), and got trouble because default PATH entries like /usr/bin were not set.
Issues:
- If the PATH from
docker inspectis empty, there's no default value (not even the "/bin:/usr/bin" hinted byman 3 execvpon Linux). Adding a reasonable standard value from some better source would help a lot (and would have avoided his issue). - This was tricky to debug because the docs were incomplete. This whole process to setup
PATHseems not described in the docs (https://docs.haskellstack.org/en/latest/docker_integration/), I had to rely on source code and comments. I'm not sure how much of this should be documented, but probably something should. For extra fun, running a shell in the container would usually show a reasonable PATH, set up by shell initialization, confusing debugging. For instance, this command showed a correct PATH:
docker run -i -t --rm $curr_image sh -c 'echo $PATH'
I wonder whether stack should fetch the PATH from this command instead ofdocker inspect: this would be less error-prone for users, but it could be a bad idea for some reason (I don't understand this code enough. - IIUC, a value of
PATHspecified manually instack.yamloverrides anything setup above, including the extra folders added by Stack, which probably causes trouble.
To see whether PATH was initialized by the Dockerfile for some container/image $NAME, one can run docker inspect -f '{{.Config.Env}}' $NAME to get the predefined environment variables, and search PATH among them.
Relevant code:
Lines 300 to 303 in 8aaef91
| newPathEnv <- augmentPath | |
| [ hostBinDirPath | |
| , sandboxHomeDir </> $(mkRelDir ".local/bin")] | |
| (T.pack <$> lookupImageEnv "PATH" imageEnvVars) |
Lines 928 to 932 in 8aaef91
| -- | Parsed @Config@ section of @docker inspect@ output. | |
| data ImageConfig = ImageConfig | |
| {icEnv :: [String] | |
| ,icEntrypoint :: [String]} | |
| deriving (Show) |
imageEnvVars comes).