I needed a base
Docker image with built-in support for toggling runtime settings – specifically, whether to use proxy settings or not. Building this into the base image presents a consistent UX for my teammates to use and an extensible framework for adding future toggles.
You can check out the repository on GitHub at neveroddoreven/alpine-bash-profile.
This is an example use case where I run the container and switch users. The full code is available on GitHub: neveroddoreven/alpine-bash-profile.
- When running a container with
docker run, a startup script must run to initialize the environment
- The startup script should accept input in the form of flags or environment variables, passed in when calling
- Regardless of user or session, automatically configure the environment based on the flags and options supplied when calling
> docker run -it --rm "neveroddoreven/alpine-bash-profile:latest" --proxies-on Welcome appuser. Setting known flags export PROXIES_ON=1 appuser ~ $ sudo su - Welcome root. Setting known flags export PROXIES_ON=1 root ~ $ exit appuser ~ $ exit >
I began by first adding some basic
apk packages to my
Dockerfile, then adding an
appuser user, and finally setting the default shell to
/bin/bash for all users.
FROM alpine:3.8 USER root # Fetch the latest apk manifests # Update existing packages # Install bash and vim # Cleanup after ourselves to keep this layer as small as possible # Details: https://wiki.alpinelinux.org/wiki/Alpine_Linux_package_management RUN apk update \ && apk upgrade \ && apk add --no-cache bash vim sudo # Add a group named "appusers" # -g, Assign this ID to the new group # Details: https://busybox.net/BusyBox.html#addgroup RUN addgroup -g 1000 appusers # Add a user named "appuser" # -D, Do not assign a password # -u, Assign this ID to the new user # -s, Set this shell as the user's default login shell # -h, Set this home path as the user's home path # -G, Add the new user to an existing group # Details: https://busybox.net/BusyBox.html#adduser RUN adduser -D -u 1000 -s /bin/bash -h /home/appuser -G appusers appuser # Alpine Linux default shell for root is '/bin/ash' # Change this to '/bin/bash' so that '/etc/bashrc' # can be loaded when entering the running container RUN sed -i 's,/bin/ash,/bin/bash,g' /etc/passwd # Add the 'appusers' group to the sudoers file # No password required RUN echo '%appusers ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers USER appuser WORKDIR /home/appuser CMD [ "bash" ]
Adding Profile Sourcing Logic
# Add our custom welcome message script to profile.d. # This is automatically sourced by /etc/profile when # switching users. COPY scripts/etc/profile.d/welcome.sh /etc/profile.d/welcome.sh # The logic in this script can be whatever you want the container to do # before running the entrypoint script. COPY scripts/etc/bashrc /etc/bashrc # This will run immediately after the /etc/bashrc script COPY scripts/usr/share/entrypoint.sh /usr/share/entrypoint.sh # Must set this value for the bash shell to source # the '/etc/bashrc' file. See: https://stackoverflow.com/q/29021704. ENV BASH_ENV /etc/bashrc # Use this path to save any files generated when starting a container. # These files are accessible to root and appuser across sessions. RUN mkdir -p /usr/share/entrypoint \ && chown appuser:appusers /usr/share/entrypoint USER appuser WORKDIR /home/appuser # This is the last necessary piece for loading the # '/etc/bashrc' file, following the 'exec' syntax. ENTRYPOINT [ "/usr/share/entrypoint.sh" ] CMD [ "bash" ]
I currently use a derivative of this to support network proxies, and I have plans to extend this to support application feature flags.