You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A persistent challenge in creating containers has been how to simply and easily add environment variables or source scripts as a part of various user shells (bash, zsh) and firing things on container startup - particularly if the thing that is starting requires root access.
Today we've dealt with this by:
Having all of our scripts add content to /etc/bash.bashrc and /etc/zsh/zshrc
Defaulting userEnvProbe to loginInteractiveShell to ensure any tool gets these variables
Recommending containers run as root, but connect tools as non-root
Creating entrypoint scripts that fall back on sudo if not running as root
If a pure login shell is used via docker exec or userEnvProbe is updated, (1) will not work. Scripts can also be added to /etc/profile.d and /etc/zsh/zprofile (or zshenv) to solve this, but you then have to check to verify whether the script has already fired if you are doing something that shouldn't happen more than once or has overhead.
For (3) and (4), sudo is not always present, and in some cases may be explicitly omitted for security reasons - particularly password-less. Running the container as root is also not a good idea on shared Linux hosts unless a VM is used to house the containers - like in Docker Desktop (which is also coming to Linux). There is "rootless" mode for container engines, but these also have limitations and end up causing problems for bind mounts since all files end up being owned by root. (Using a container volume does not have this limitation, however).
For (5), currently the feature needs to be reference even if it is built into the container image. This can be quite confusing and easy to forget. In addition, adding an explicit entrypoint to a Dockerfile also requires overrideCommand to be set to false which has similar challenges - though the label metadata proposal could help here (Dev container metadata in image labels #18).
Proposal
Rather than all of this, we can have a well defined pattern when features are used. There could even be a simple feature that does nothing more than set up execution of this pattern. Instead of everything described above, we can introduce two well known folder locations:
A profile.d folder (or a similar name). If a feature places a script in this location, it will be sourced by /etc/bash.bashrc, /etc/zsh/zshrc, /etc/profile.d, and /etc/zsh/zprofile. A single bootstrapper can then be sourced to ensure these scripts are executed with code similar to what you'd find in /etc/profile. However, it would check to see if the bootstrapper has already run to ensure it doesn't fire more than once like in the case of a login interactive shell.
An entrypoint.d folder where you can place a scripts that will automatically be executed as a part of the container startup. This eliminates the need for an explicit entrypoint property in devcontainer-features.json. However, execution is a bit different than profile.d. It should:
Be explicitly added to the container's entrypoint if not present already.
Execute the scripts in alphabetical order so that, like /etc/profile.d, you can add numeric prefixes to indicate when it should happen.
The processor should then fire exec for any arguments passed into it so that the PID for the processor is replaced by the existing entrypoint commands.
Features then follow a pattern of placing contents in these folders rather than attempting to manually update configuration.
Alternatives
Part of the reason for entrypoint.d is that most containers do not have systemd or another init system that supports process startup. (The tiny init system that the --init argument adds does not manage process startup). The challenge is systemd is heavy and requires more permissions to the host than is ideal. So while it is an option, its not something we could count on. An alternative would be to use something like supervisord. However, if the desire is just to fire something once at startup rather than keep a process running, its overkill as well. We can also easily document how to wire in supervisord using entrypoint.d if not provide a dev container feature for it.
A persistent challenge in creating containers has been how to simply and easily add environment variables or source scripts as a part of various user shells (bash, zsh) and firing things on container startup - particularly if the thing that is starting requires root access.
Today we've dealt with this by:
userEnvProbetologinInteractiveShellto ensure any tool gets these variablesThere are several challenges here.
overrideCommandto be set to false which has similar challenges - though the label metadata proposal could help here (Dev container metadata in image labels #18).Proposal
Rather than all of this, we can have a well defined pattern when features are used. There could even be a simple feature that does nothing more than set up execution of this pattern. Instead of everything described above, we can introduce two well known folder locations:
A
profile.dfolder (or a similar name). If a feature places a script in this location, it will be sourced by /etc/bash.bashrc, /etc/zsh/zshrc, /etc/profile.d, and /etc/zsh/zprofile. A single bootstrapper can then be sourced to ensure these scripts are executed with code similar to what you'd find in /etc/profile. However, it would check to see if the bootstrapper has already run to ensure it doesn't fire more than once like in the case of a login interactive shell.An
entrypoint.dfolder where you can place a scripts that will automatically be executed as a part of the container startup. This eliminates the need for an explicit entrypoint property indevcontainer-features.json. However, execution is a bit different thanprofile.d. It should:/etc/profile.d, you can add numeric prefixes to indicate when it should happen.execfor any arguments passed into it so that the PID for the processor is replaced by the existing entrypoint commands.Features then follow a pattern of placing contents in these folders rather than attempting to manually update configuration.
Alternatives
Part of the reason for
entrypoint.dis that most containers do not have systemd or another init system that supports process startup. (The tiny init system that the --init argument adds does not manage process startup). The challenge is systemd is heavy and requires more permissions to the host than is ideal. So while it is an option, its not something we could count on. An alternative would be to use something like supervisord. However, if the desire is just to fire something once at startup rather than keep a process running, its overkill as well. We can also easily document how to wire in supervisord usingentrypoint.dif not provide a dev container feature for it.