├── .gitignore ├── .gitlab-ci.yml ├── .gitmodules ├── README.md ├── buildall ├── copyreadme ├── pushall2docker └── pushbranches /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | docker-build-master: 2 | # Official docker image. 3 | image: docker:latest 4 | stage: build 5 | services: 6 | - docker:dind 7 | before_script: 8 | - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY 9 | script: 10 | - umask 0022 11 | - apk add git 12 | - apk add bash 13 | - apk add curl 14 | - git submodule init 15 | - git submodule update 16 | - chmod -R og-w . 17 | - ./buildall 18 | - ./pushall2docker 19 | - "curl -X POST -F token=$CI_DOCKER_NNCP_TRIGGER -F ref=main https://salsa.debian.org/api/v4/projects/67697/trigger/pipeline" 20 | - "curl -X POST -F token=$CI_DOCKER_APACHE_PROXY_TRIGGER -F ref=master https://salsa.debian.org/api/v4/projects/67698/trigger/pipeline" 21 | - "curl -X POST -F token=$CI_DOCKER_TOR_TRIGGER -F ref=master https://salsa.debian.org/api/v4/projects/67701/trigger/pipeline" 22 | - "curl -X POST -F token=$CI_DOCKER_AMPACHE_TRIGGER -F ref=master https://salsa.debian.org/api/v4/projects/67750/trigger/pipeline" 23 | - "curl -X POST -F token=$CI_DOCKER_WEEWX_TRIGGER -F ref=master https://salsa.debian.org/api/v4/projects/67751/trigger/pipeline" 24 | - "curl -X POST -F token=$CI_DOCKER_UUCP_TRIGGER -F ref=master https://salsa.debian.org/api/v4/projects/67766/trigger/pipeline" 25 | - "curl -X POST -F token=$CI_DOCKER_MYTHTV_TRIGGER -F ref=master https://salsa.debian.org/api/v4/projects/67769/trigger/pipeline" 26 | 27 | 28 | only: 29 | - master 30 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "debian-base-apache"] 2 | path = debian-base-apache 3 | url = https://salsa.debian.org/jgoerzen/docker-debian-base-apache.git 4 | branch = . 5 | [submodule "debian-base-minimal"] 6 | path = debian-base-minimal 7 | url = https://salsa.debian.org/jgoerzen/docker-debian-base-minimal.git 8 | branch = . 9 | [submodule "debian-base-apache-php"] 10 | path = debian-base-apache-php 11 | url = https://salsa.debian.org/jgoerzen/docker-debian-base-apache-php.git 12 | branch = . 13 | [submodule "debian-base-vnc"] 14 | path = debian-base-vnc 15 | url = https://salsa.debian.org/jgoerzen/docker-debian-base-vnc.git 16 | branch = . 17 | [submodule "debian-base-standard"] 18 | path = debian-base-standard 19 | url = https://salsa.debian.org/jgoerzen/docker-debian-base-standard.git 20 | branch = . 21 | [submodule "debian-base-security"] 22 | path = debian-base-security 23 | url = https://salsa.debian.org/jgoerzen/docker-debian-base-security.git 24 | branch = . 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Debian Working System for Docker 2 | 3 | **NOTE: Github is no longer the home for this project; see the [new home on Salsa](https://salsa.debian.org/jgoerzen/docker-debian-base)**. 4 | 5 | This image is part of the 6 | [docker-debian-base](https://salsa.debian.org/jgoerzen/docker-debian-base) 7 | image set. 8 | 9 | This is a simple set of images that transform the standard Docker 10 | Debian environment into one that provides more traditional full 11 | Unix APIs (including syslog, zombie process collection, etc.) 12 | 13 | Despite this, they are all very small, both in terms of disk and RAM usage. 14 | 15 | You can find a [description of the motivation for these images](https://changelog.complete.org/archives/9794-fixing-the-problems-with-docker-images) on my blog. 16 | 17 | This is loosely based on the concepts, but not the code, in the 18 | [phusion baseimage-docker](https://github.com/phusion/baseimage-docker). 19 | You can look at that link for additional discussion on the motivations. 20 | 21 | You can find the source and documentation at the [Salsa page](https://salsa.debian.org/jgoerzen/docker-debian-base) 22 | and automatic builds are available from [my Docker hub page](https://hub.docker.com/u/jgoerzen/). The builds are auto-generated from Salsa CI and run at least weekly. 23 | 24 | **OUDATED**: For stretch and jessie, this image uses sysvinit instead of systemd, 25 | not because of any particular opinion on the merits of them, but 26 | rather because sysvinit does not require any kind of privileged Docker 27 | or cgroups access. 28 | 29 | For buster and bullseye, systemd contains the necessary support for running in an 30 | unprivileged Docker container and, as it doesn't require the hacks 31 | that sysvinit does, is used there. The systemd and sysvinit images 32 | provide an identical set of features and installed software, which 33 | target the standard Linux API. 34 | 35 | Here are the images I provide from this repository: 36 | 37 | - [jgoerzen/debian-base-minimal](https://salsa.debian.org/jgoerzen/docker-debian-base-minimal) - a minimalistic base for you. 38 | - Provides working sysvinit/systemd, syslogd, cron, anacron, at, and logrotate. 39 | - syslogd is configured to output to the docker log system by default. 40 | - [jgoerzen/debian-base-standard](https://salsa.debian.org/jgoerzen/docker-debian-base-standard) - adds some utilities. Containes everything above, plus: 41 | - Utilities: less, nano, vim-tiny, man-db (for viewing manpages), net-tools, wget, curl, pwgen, zip, unzip 42 | - Email: exim4-daemon-light, mailx 43 | - Network: netcat-openbsd, socat, openssl, ssh, telnet (client) 44 | - [jgoerzen/debian-base-security](https://salsa.debian.org/jgoerzen/docker-debian-base-security) - A great way to keep things updated. Contains everything above, plus: 45 | - automated security patches using unattended-upgrades and needrestart 46 | - debian-security-support 47 | - At container initialization, runs the unattended-upgrade code path to ensure that the 48 | system is up-to-date before services are exposed to the Internet. This addresses an 49 | issue wherein security patches may hit security.debian.org before Docker 50 | images are refreshed, a fairly common issue with the Docker infrastructure. 51 | This behavior can be suppressed with `DEBBASE_NO_STARTUP_APT` (see below). 52 | - [jgoerzen/debian-base-vnc](https://salsa.debian.org/jgoerzen/docker-debian-base-vnc) - For systems that need X. debian-base-security, plus: 53 | - tightvncserver, xfonts-base, lwm, xterm, xdotool, xvnc4viewer 54 | - [jgoerzen/debian-base-apache](https://salsa.debian.org/jgoerzen/docker-debian-base-apache) - A web server - debian-base-security, plus: 55 | - apache2 plus utilities: ssl-cert 56 | - LetsEncrypt options: certbot, acme-tiny 57 | - [jgoerzen/debian-base-apache-php](https://salsa.debian.org/jgoerzen/docker-debian-base-apache-php) - debian-base-apache, plus: 58 | - libapache2-mod-php (mod-php5 on jessie) 59 | 60 | Memory usage at boot (stretch): 61 | 62 | - jgoerzen/debian-base-minimal: 6MB 63 | - jgoerzen/debian-base-standard: 11MB 64 | - jgoerzen/debian-base-security: 11MB 65 | 66 | # Docker Tags 67 | 68 | These tags are autobuilt: 69 | 70 | - latest: whatever is stable (currently bullseye, systemd) 71 | - bullseye: Debian bullseye (systemd) 72 | - buster: Debian buster (systemd) 73 | - stretch: Debian stretch (sysvinit) - **no longer supported, may be removed at any time** 74 | - jessie: Debian jessie (sysvinit) - **no longer supported, may be removed at any time** 75 | - sid: Debian sid (not tested; systemd) 76 | 77 | # Install 78 | 79 | You can install with: 80 | 81 | docker pull jgoerzen/debian-base-whatever 82 | 83 | Your Dockerfile should use CMD to run `/usr/local/bin/boot-debian-base`. 84 | 85 | When running, use `-t` to enable the logging to `docker logs` 86 | 87 | # Container Invocation 88 | 89 | A container should be started using these commands, among others. See 90 | also the section on environment variables, below. 91 | 92 | ## Container Invocation, systemd containers (buster/bullseye/sid) 93 | 94 | Here's how you invoke for systemd (buster/bullseye) on a system running an older systemd on the host, with cgroups v1: 95 | 96 | docker run -td --stop-signal=SIGRTMIN+3 \ 97 | --tmpfs /run:size=100M --tmpfs /run/lock:size=100M \ 98 | -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ 99 | --name=name jgoerzen/debian-base-whatever 100 | 101 | For a host running bullseye, or a newer cgroups and systemd, you have to use this: 102 | 103 | docker run -td --stop-signal=SIGRTMIN+3 \ 104 | --tmpfs /run:size=100M --tmpfs /run/lock:size=100M \ 105 | -v /sys/fs/cgroup:/sys/fs/cgroup:rw --cgroupns=host \ 106 | --name=name jgoerzen/debian-base-whatever 107 | 108 | Note that the buster image has not been tested under these situations, and since bullseye is now stable, it is the recommended image for all modern deployments. 109 | 110 | The `/run` and `/run/lock` tmpfs are required by systemd. The 100M 111 | sets a maximum size, not a default allocation, and serves to limit the 112 | amount of RAM an errant process could cause the system to consume, 113 | down from a default limit of 16G. 114 | 115 | Note that these images, contrary to many others out there, do NOT 116 | require `--privileged`. 117 | 118 | For more information about the systemd/cgroups situation, consult these links 119 | 120 | - https://github.com/systemd/systemd/issues/19245 121 | - https://github.com/containers/podman/issues/5153 122 | - https://github.com/moby/moby/issues/42275 123 | - https://serverfault.com/questions/1053187/systemd-fails-to-run-in-a-docker-container-when-using-cgroupv2-cgroupns-priva/1054414#1054414 124 | - http://docs.podman.io/en/latest/markdown/podman-run.1.html#cgroupns-mode 125 | - 126 | 127 | ## Container Invocation, sysvinit containers (jessie/stretch) 128 | 129 | docker run -td --stop-signal=SIGPWR --name=name jgoerzen/debian-base-whatever 130 | 131 | # Environment Variables 132 | 133 | This environment variable is available for your use: 134 | 135 | - `DEBBASE_SYSLOG` defaults to `stdout`, which redirects all syslog activity 136 | to the Docker infrastructure. If you instead set it to `internal`, it will 137 | use the default Debian configuration of logging to `/var/log` within the 138 | container. The configuration is applied at container start time by 139 | adjusting the `/etc/syslog.conf` symlink to point to either `syslog.conf.internal` or 140 | `syslog.conf.stdout`. `syslog.conf.internal` is the default from the system. 141 | `dpkg-divert` is used to force all packages' attempts to write to `/etc/syslog.conf` 142 | to instead write to `/etc/syslog.conf.internal`. 143 | - `DEBBASE_TIMEZONE`, if set, will configure the `/etc/timezone` and `/etc/localtime` 144 | files in the container to the appropriate timezone. Set this to the desired timezone; 145 | for instance, `America/Denver`. 146 | - `DEBBASE_SSH` defaults to `disabled`. If you set to `enabled`, then the SSH server 147 | will be run. 148 | - `DEBBASE_NO_STARTUP_APT` defaults to empty. If set, it will cause images based 149 | on debian-base-security to skip the apt job run at container startup. 150 | 151 | # Container initialization 152 | 153 | Executables or scripts may be placed in `/usr/local/preinit`, which will be executed 154 | at container start time by `run-parts` prior to starting init. These can 155 | therefore perform container startup steps. A script which needs to only run 156 | once can delete itself after a successful run to prevent a future execution. 157 | 158 | # Orderly Shutdown 159 | 160 | The `--stop-signal` clause in the "Container Invocation" section above 161 | helps achieve an orderly shutdown. 162 | 163 | If you start without `--stop-signal`, you can instead use these steps: 164 | 165 | # jessie or stretch use this line: 166 | docker kill -s SIGPWR container 167 | # bullseye, buster or sid use this one: 168 | docker kill -s SIGRTMIN+3 container 169 | 170 | # Either way, then proceed with: 171 | sleep 10 172 | docker kill container 173 | 174 | Within the container, you can call `telinit 1` (jessie/stretch) or 175 | `poweroff` (bullseye/buster/sid) to cause the container to shutdown. 176 | 177 | ## Advanted topic: Orderly Shutdown Mechanics 178 | 179 | By default, `docker stop` sends the SIGTERM (and, later, SIGKILL) 180 | signal to PID 1 (init) iniside a container. Neither sysvinit nor 181 | systemd act upon this signal in a useful way. This will shut down a 182 | container, but it will not give your shutdown scripts the chance to 183 | run gracefully. In many situations, this is fine, but it may not be 184 | so in all. 185 | 186 | A workaround is, howerver, readily available, without modifying init. These 187 | images are configured to perform a graceful shutdown upon receiving 188 | `SIGPWR` (jessie/stretch) or `SIGRTMIN+3` (bullseye/buster/sid). 189 | 190 | The process for this with sysvinit is... interesting, since we are 191 | unable to directly kill PID 1 inside a docker container. First, init 192 | calls `/etc/init.d/powerfail`. The powerfail script I install simply 193 | tells init to go to single-user mode. This causes it to perform an 194 | orderly shutdown of the daemons, and when it is done, it invokes 195 | `/sbin/sulogin`. On an ordinary system, this prompts for the root 196 | password for single-user mode. In this environment, we instead 197 | symlink /sbin/init to /bin/true, then tell init to re-exec itself. 198 | This causes PID 1 to finally exit. 199 | 200 | With sysvinit, one of the preinit scripts makes sure that `/sbin/init` 201 | properly links to `/sbin/init.real` at boot time. 202 | 203 | With systemd in bullseye/buster/sid, no special code for all this is needed; 204 | systemd handles it internally with no fuss. 205 | 206 | # Configuration 207 | 208 | Although the standard and security images run the SMTP and SSH servers, 209 | they do not expose these to the Internet by default. Both require 210 | site-specific configuration before they are actually useful. 211 | 212 | Because the SMTP service is used inside containers, but the SSH service 213 | generally is not, the SSH service is disabled by default. 214 | 215 | ## Enabling or Disabling Services 216 | 217 | You can enable or disable services using commands like this 218 | (jessie/stretch): 219 | 220 | update-rc.d ssh disable 221 | update-rc.d ssh enable 222 | 223 | Or this (bullseye/buster/sid): 224 | 225 | systemctl disable ssh 226 | systemctl enable ssh 227 | 228 | (Note, that in the case of ssh, the environment variable will cause 229 | commands like this to be executed automatically on each container 230 | start.) 231 | 232 | ## Email 233 | 234 | email is the main thing you'd need to configure. In the running system, 235 | `dpkg-reconfigure -plow exim4-config` will let you do this. 236 | 237 | ## SSH 238 | 239 | SSH host keys will be generated upon first run of a container, if 240 | they do not already exist. This implies every instantiation 241 | of a container containing SSH will have a new random host key. 242 | If you want to override this, you can of course supply your own 243 | files in `/etc/ssh` or make it a volume. 244 | 245 | # Advanced topic: programs that depend on disabled scripts (stretch/jessie only) 246 | 247 | **This section pertains only to stretch/jessie; systemd in bullseye/buster/sid 248 | does not have these issues.** 249 | 250 | There are a number of scripts in `/etc/init.d` that are normally part 251 | of a Debian system initialization, but fail in a Docker environment. 252 | They do things like set up swap space, mount filesystems, etc. Docker 253 | images typically leave those scripts in place, but they are never 254 | called because Docker systems typically don't run a real init like 255 | these images do. 256 | 257 | Although calling the scripts produces nothing worse than harmless 258 | errors, I have disabled those scripts in these images in order to 259 | avoid putting useless error messages in people's log files. In some 260 | very rare circumstances, this may cause installation of additional 261 | packages to fail due to boot script dependency ordering not working 262 | right. (Again, this is very rare). 263 | 264 | I saw this happen once where a package had a long chain of 265 | dependencies that wound up pulling in cgmanager, which died in 266 | postinst complaining that its init script required `mountkernfs`. I 267 | worked around this in my Dockerfile like this: 268 | 269 | update-rc.d mountkernfs.sh defaults 270 | apt-get -y --no-install-recommends offending-package 271 | update-rc.d -f cgmanager remove 272 | update-rc.d -f mountkernfs.sh remove 273 | 274 | Also, I have blocked systemd from accidentally being installed on the 275 | system. There are a few packages that pull in systemd shims and so 276 | forth, so if you get errors about systemd not installing, try adding 277 | `rm /etc/apt/preferences.d/systemd` to your Dockerfile. 278 | 279 | # Advanced Topic: Adding these enhancements to other images 280 | 281 | Sometimes, it is desirable to not have to rebuild an image entirely. 282 | These images are also designed to make it easy to add the 283 | functionality to other images. You can do this by using the support 284 | for multiple FROM lines in a Dockerfile. For instance, here's a 285 | simple one I worked up: 286 | 287 | FROM jgoerzen/debian-base-security:jessie AS debian-addons 288 | 289 | FROM homeassistant/home-assistant:0.63.1 290 | 291 | COPY --from=debian-addons /usr/local/preinit/ /usr/local/preinit/ 292 | COPY --from=debian-addons /usr/local/bin/ /usr/local/bin/ 293 | COPY --from=debian-addons /usr/local/debian-base-setup/ /usr/local/debian-base-setup/ 294 | 295 | RUN run-parts --exit-on-error --verbose /usr/local/debian-base-setup 296 | CMD ["/usr/local/bin/boot-debian-base"] 297 | 298 | It happens that home-assistant is based on a Python image which, in 299 | turn, is based on Debian jessie. There are just those four lines that 300 | are needed: copying the /usr/local/preinit, bin, and debian-base-setup 301 | directories, and then the `run-parts` call. This effectively adds all 302 | the features of debian-base-security to the home-assistant image. 303 | 304 | This works because each image that is part of the chain leading up to 305 | security (minimal, standard, and security) performs all of its 306 | activity from scripts it drops -- and leaves -- in 307 | `/usr/local/debian-base-setup`. Those scripts need nothing other than 308 | the files in the three directories referenced above. By adding those 309 | three directories and calling the scripts, it is easy to add these 310 | features to other images. 311 | 312 | # Source 313 | 314 | This is prepared by John Goerzen and the source 315 | can be found at https://salsa.debian.org/jgoerzen/docker-debian-base 316 | 317 | # See Also 318 | 319 | Some references to additional information: 320 | 321 | - systemd's 322 | [contianer interface documentation](https://www.freedesktop.org/wiki/Software/systemd/ContainerInterface/) 323 | - [Article](https://developers.redhat.com/blog/2016/09/13/running-systemd-in-a-non-privileged-container/) 324 | on running systemd in a container. Highlights some of the reasons 325 | to do so: providing a standard Linux API, reaping zombie processes, 326 | handling of logging, not having to re-implement init, etc. All of 327 | these have already been implemented in these images with sysvinit 328 | and continue with systemd. 329 | - [serverfault thread](https://serverfault.com/questions/607769/running-systemd-inside-a-docker-container-arch-linux) 330 | 331 | # Copyright 332 | 333 | Docker scripts, etc. are 334 | Copyright (c) 2017-2019 John Goerzen 335 | All rights reserved. 336 | 337 | Redistribution and use in source and binary forms, with or without 338 | modification, are permitted provided that the following conditions 339 | are met: 340 | 1. Redistributions of source code must retain the above copyright 341 | notice, this list of conditions and the following disclaimer. 342 | 2. Redistributions in binary form must reproduce the above copyright 343 | notice, this list of conditions and the following disclaimer in the 344 | documentation and/or other materials provided with the distribution. 345 | 3. Neither the name of the University nor the names of its contributors 346 | may be used to endorse or promote products derived from this software 347 | without specific prior written permission. 348 | 349 | THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 350 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 351 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 352 | ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 353 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 354 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 355 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 356 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 357 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 358 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 359 | SUCH DAMAGE. 360 | 361 | Additional software copyrights as noted. 362 | 363 | -------------------------------------------------------------------------------- /buildall: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | set -x 4 | 5 | buildbranch() { 6 | for DIR in debian-base-{minimal,standard,security,vnc,apache,apache-php}; do 7 | cd $DIR 8 | git checkout $1 9 | docker build -t jgoerzen/$DIR:$2 . 10 | docker tag jgoerzen/$DIR:$2 jgoerzen/$DIR:$3 11 | cd .. 12 | done 13 | } 14 | 15 | buildbranch master latest bullseye 16 | #buildbranch jessie jessie 17 | #git checkout master 18 | 19 | -------------------------------------------------------------------------------- /copyreadme: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | set -x 5 | 6 | copyreadme () { 7 | # arg $1 is name of branch we're on 8 | for SUBDIR in debian-base-*; do 9 | cp README.md "$SUBDIR/README.md" 10 | done 11 | git submodule foreach "git checkout $1; git commit -m 'Update README.md from docker-debian-base/README.perimage.md' README.md" 12 | } 13 | 14 | if [ "$1" = "--allbranches" ]; then 15 | for BRANCH in `git branch '--format=%(refname:lstrip=2)'`; do 16 | git checkout "$BRANCH" 17 | git merge master 18 | git submodule update --remote 19 | copyreadme "$BRANCH" 20 | done 21 | git checkout master 22 | else 23 | copyreadme `git branch | grep '\*' | awk '{ print $2 }'` 24 | fi 25 | -------------------------------------------------------------------------------- /pushall2docker: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | set -x 4 | 5 | buildbranch() { 6 | for DIR in debian-base-{minimal,standard,security,vnc,apache,apache-php}; do 7 | cd $DIR 8 | git checkout $1 9 | docker push jgoerzen/$DIR:$2 10 | docker push jgoerzen/$DIR:$3 11 | cd .. 12 | done 13 | } 14 | 15 | buildbranch master latest bullseye 16 | #buildbranch jessie jessie 17 | #git checkout master 18 | 19 | -------------------------------------------------------------------------------- /pushbranches: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | set -x 5 | 6 | pushbranch () { 7 | # arg $1 is name of branch we're on 8 | git submodule foreach "git push origin HEAD:$1 && git checkout $1 && git merge origin/$1" 9 | } 10 | 11 | if [ "$1" = "--allbranches" ]; then 12 | for BRANCH in `git branch '--format=%(refname:lstrip=2)'`; do 13 | pushbranch "$BRANCH" 14 | done 15 | else 16 | #pushbranch `git branch | grep '\*' | awk '{ print $2 }'` 17 | git submodule foreach "git push" 18 | fi 19 | --------------------------------------------------------------------------------