A tiny multiarch Alpine Linux Docker image.
386 | amd64 | arm/v6 | arm/v7 | arm64 | ppc64le | s390x | riscv64 |
---|---|---|---|---|---|---|---|
✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
With only ~50 KB on top of Alpine, this image provides:
- an init system (tini) (~30 KB)
- a modular entrypoint (~3 KB), and
- automatic privilege lowering (via su-exec) (~20 KB).
The following environment variables are exposed to control the entrypoint. They may be set:
- either within a Dockerfile (using the
ENV
statement), and/or - directly during
docker run
(using the-e
command-line flag).
DOCKER_UID
(default:"12345"
)DOCKER_GID
(default:"23456"
)DOCKER_USER
(default:"user"
)DOCKER_GROUP
(default:"user"
)
ENTRYPOINT_D
(default:"/etc/docker-entrypoint.d"
): Location of configuration scriptsENTRYPOINT_RUN_AS_ROOT
(default:""
): If non-empty, disables privilege lowering!ENTRYPOINT_SKIP_CONFIG
(default:""
): If non-empty, disables running configuration scriptsENTRYPOINT_LOG_THRESHOLD
(default:1
): Set the minimum level for log messages to be displayed
Log levels:1
(or lower) = debug,2
= info,3
= warning,4
= error,5
(or greater) = disable
Additional configuration scripts may be placed in the ENTRYPOINT_D
directory to be run before the CMD
.
The entrypoint will execute all executable scripts, i.e. all .sh
files with the executable (x
) bit set.
You may:
- either populate these scripts in your Dockerfile (using the
COPY
statement), and/or - mount them directly during
docker run
(using the-v
command-line flag).
FROM padhihomelab/alpine-base
# Modify default values for environment variables, if desired
ENV ENTRYPOINT_LOG_THRESHOLD 3
# Install additional configuration scripts, if required
COPY config_scripts/*.sh ${ENTRYPOINT_D}/
RUN chmod +x ${ENTRYPOINT_D}/*.sh
# ... your stuff ...
Just make you sure you don't change the entrypoint for the image,
i.e. the ENTRYPOINT
statement should not appear in your Dockerfile.
Typically you would want to at least set the DOCKER_UID
environment variable
when running a container that uses this image.
$ docker run -e DOCKER_UID=`id -u` -i padhihomelab/alpine-base ps aux
2020-11-22 11:27:43 docker-entrypoint (INFO) Creating new group 'user' with GID = 23456 ...
2020-11-22 11:27:43 docker-entrypoint (DBUG) + Group created successfully.
2020-11-22 11:27:43 docker-entrypoint (INFO) Creating new user 'user' with UID = 1000 in group 'user' ...
2020-11-22 11:27:43 docker-entrypoint (DBUG) + User created successfully.
2020-11-22 11:27:43 docker-entrypoint (INFO) No files found in /etc/docker-entrypoint.d, skipping configuration.
2020-11-22 11:27:43 docker-entrypoint (INFO) Ready for start up!
PID USER TIME COMMAND
1 root 0:00 tini /usr/local/bin/docker-entrypoint ps aux
6 user 0:00 ps aux
Yes, in most cases when you are writing to the host filesystem. If you are only doing read-only operations, or are not using host volumes, then you need not worry about setting these variables.
First of all, without privilege lowering, the files written to the host system will be owned by root, and dealing with them from a non-root account on the host system would be painful.
With privilege lowering, the files written to the host system will be owned by $DOCKER_UID
,
which may not be identical to the actual UID of the user (on the host system) running the container.
So again, dealing with the newly written files outside of the container will be painful.
For more details, please also see @vsupalov's blog post: "Avoiding Permission Issues With Docker-Created Files".
What is tini? Do I really need it?
tini is an extremely light-weight init system.
Please see "Why you need an init system" (by @Yelp) for an excellent in-depth discussion.
Why not dumb-init or another init system?
The main reason is that tini supports subreaping of Zombie processes, which dumb-init does not. For concrete examples on why this is an important issue, please see Hongli Lai's excellent blog post: "Docker and the PID 1 zombie reaping problem".
For more details, please also see:
- "dumb-init or tini" gist (by @StevenACoffman)
- "Why Tini?" README page (by @krallin)
What is su-exec? Do I really need it?
su-exec lowers the privilege from root
to $DOCKER_USER
before running the command.
In most cases, you should need it, unless you absolutely do need to run the container as root.
There are several articles on why this is a major security issue. Please see:
- Docker containers with root privileges blog post by (Maciej Solnica)
- Less capabilities, more security: minimize privilege escalation in Docker blog post (by Itamar Tuerner-Trauring)
The main reason is that su-exec is significantly smaller than gosu, and doesn't inherit the quirks of su and sudo.
For more details, please also see:
- gosu:Why? and gosu:Alternatives README pages (by @tianon)
- gosu or su-exec gist (by @StevenACoffman)
Why not use a supervision suite, like s6?
s6 is great. It actually subsumes both tini and su-exec, and provides many more utilities.
However, it's a little too heavyweight for most of my use cases. Most of my images run on small SBCs and I try to make them as tiny and lightweight as possible.