From d7985cddfff2703a26468fbd1774c7877f31336c Mon Sep 17 00:00:00 2001 From: Barak Korren Date: Wed, 27 Nov 2019 16:27:19 +0200 Subject: [PATCH] Updated base image and some more functionality 1. Rebased the image on the fedora:31 image 2. Removed all env-var handling code as its basically superseded by the systemd `PassEnvironment` option that can be specified on a per-unit-file basis 3. Made systemd and journald output go to `/dev/console` which should be collected by the container engine automatically 4. Made a new service unit file that tries to run the arguments given to the container as commands after all systemd services have started and exit the container once those commands are done while returning an appropriate return value. 5. It is possible to have environment variables passed to the invoked commands by setting variable names in the `ARGS_ENV_INCLUDE` variable either when launching the container or when building derived containers Note: The CentOs version upgrade is required, among other things, because the `systemd` version in CentOS 7 does not support returning exit codes on exit. Note: Certain versions of Docker have an issue with collecting `/dev/console` properly. See the following for explanation: - https://github.com/systemd/systemd/pull/4262 - https://github.com/moby/moby/issues/27202 - https://bugzilla.redhat.com/show_bug.cgi?id=1373780 This image also include a workaround for the following Podman issue: - https://github.com/containers/libpod/issues/4625 Signed-off-by: Barak Korren --- .dockerignore | 1 + .gitignore | 1 + Dockerfile | 20 +++++++----- etc/systemd/journald.conf | 42 ++++++++++++++++++++++++++ etc/systemd/system/run-args.service.in | 14 +++++++++ sbin/entrypoint.sh | 25 +++++++++++++++ sbin/export_environment.sh | 29 ------------------ sbin/run_args.sh | 20 ++++++++++++ systemd/export-environment.service | 9 ------ 9 files changed, 116 insertions(+), 45 deletions(-) create mode 100644 .dockerignore create mode 100644 .gitignore create mode 100644 etc/systemd/journald.conf create mode 100644 etc/systemd/system/run-args.service.in create mode 100755 sbin/entrypoint.sh delete mode 100644 sbin/export_environment.sh create mode 100755 sbin/run_args.sh delete mode 100644 systemd/export-environment.service diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..1377554 --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +*.swp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1377554 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.swp diff --git a/Dockerfile b/Dockerfile index 17097b6..5e37890 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,8 @@ -FROM centos:7.6.1810 +FROM fedora:31 ENV container docker +VOLUME ["/sys/fs/cgroup"] + RUN ( \ cd /lib/systemd/system/sysinit.target.wants/; \ for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done \ @@ -13,9 +15,13 @@ RUN ( \ rm -f /lib/systemd/system/basic.target.wants/*; \ rm -f /lib/systemd/system/anaconda.target.wants/*; \ touch /etc/sysconfig/network -COPY sbin/export_environment.sh /sbin/export_environment -COPY systemd/* /etc/systemd/system/ -RUN chmod +x /sbin/export_environment -RUN systemctl enable export-environment.service -VOLUME ["/sys/fs/cgroup"] -CMD ["/usr/sbin/init"] + +COPY sbin/ /sbin/ +COPY etc/ /etc/ + +ENV ARGS_EXPORT_PATH=/etc/ci-container.args +# A list of variables to be made available in the environment the given command +# line args run in +ENV ARGS_ENV_INCLUDE="ARGS_EXPORT_PATH" + +ENTRYPOINT ["/sbin/entrypoint.sh"] diff --git a/etc/systemd/journald.conf b/etc/systemd/journald.conf new file mode 100644 index 0000000..9417083 --- /dev/null +++ b/etc/systemd/journald.conf @@ -0,0 +1,42 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# Entries in this file show the compile time defaults. +# You can change settings by editing this file. +# Defaults can be restored by simply deleting this file. +# +# See journald.conf(5) for details. + +[Journal] +#Storage=auto +#Compress=yes +#Seal=yes +#SplitMode=uid +#SyncIntervalSec=5m +#RateLimitIntervalSec=30s +#RateLimitBurst=10000 +#SystemMaxUse= +#SystemKeepFree= +#SystemMaxFileSize= +#SystemMaxFiles=100 +#RuntimeMaxUse= +#RuntimeKeepFree= +#RuntimeMaxFileSize= +#RuntimeMaxFiles=100 +#MaxRetentionSec= +#MaxFileSec=1month +#ForwardToSyslog=no +#ForwardToKMsg=no +ForwardToConsole=yes +#ForwardToWall=yes +TTYPath=/dev/console +#MaxLevelStore=debug +#MaxLevelSyslog=debug +#MaxLevelKMsg=notice +MaxLevelConsole=debug +#MaxLevelWall=emerg +#LineMax=48K diff --git a/etc/systemd/system/run-args.service.in b/etc/systemd/system/run-args.service.in new file mode 100644 index 0000000..ac7fec5 --- /dev/null +++ b/etc/systemd/system/run-args.service.in @@ -0,0 +1,14 @@ +[Unit] +Description=Run container command + +[Service] +Type=oneshot +PassEnvironment=ARGS_EXPORT_PATH $ARGS_ENV_INCLUDE +# Remove this service file so that if the container layer is committed, the +# resulting image will not contain the given command information +ExecStartPre=-/usr/bin/systemctl disable --no-reload run-args.service +ExecStartPre=-/usr/bin/rm -f /etc/systemd/system/run-args.service +ExecStart=/sbin/run_args.sh ${ARGS_EXPORT_PATH} + +[Install] +WantedBy=multi-user.target diff --git a/sbin/entrypoint.sh b/sbin/entrypoint.sh new file mode 100755 index 0000000..f0e9ebc --- /dev/null +++ b/sbin/entrypoint.sh @@ -0,0 +1,25 @@ +#!/bin/bash -e +# Read command-line arguments and store them in a file to be used later +# +if [[ $# -gt 0 ]] && [[ $1 ]]; then + # Podman seems to have an issue where `podman commit` cannot create images + # without a CMD setting, and adding `--change='CMD []'` results in the + # command being an array with a single string in it. Therefor we detect that + # particular case above and treat it as if a command was not given + echo "Got $# command-line arguments, enabling run-args service" + printf '%s\n' "$@" > "$ARGS_EXPORT_PATH" + # Update list of variables that systemd will pass to invoked process on the + # fly. Unfortunately this dirty `sed` is the only way to do that + # + # We create the *.service file from in *.service.in file rather then making + # the change to the file in-place, so that the change can be undone without + # leaving overlayfs records behind + # + /usr/bin/sed -re "s/\\\$ARGS_ENV_INCLUDE/$ARGS_ENV_INCLUDE/" \ + /etc/systemd/system/run-args.service.in \ + > /etc/systemd/system/run-args.service \ + # Enable service to run the arguments + systemctl enable run-args.service +fi + +exec /usr/sbin/init diff --git a/sbin/export_environment.sh b/sbin/export_environment.sh deleted file mode 100644 index 5232de3..0000000 --- a/sbin/export_environment.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash -xe -# -# export_environment.sh - copy selected environment variables from pid 1 -# and place in a well known location. It allows us to have systemd as the -# entry point of the container but still have the ability to pass environment -# variables through cli. -# - -# An array of variables to be exported to $export_path -INCLUDE_LIST=($(cat /etc/export_list ||:)) - -main() { - local export_path="${1:?}" - local include - - [[ ${#INCLUDE_LIST[@]} -eq 0 ]] && return - - include=$(join "${INCLUDE_LIST[@]}") - /usr/bin/tr \\000 \\n < /proc/1/environ | - grep -E "^($include)=" >> "$export_path" - chmod 0644 "$export_path" -} - -join() { - local IFS="|" - echo "$*" -} - -main "$@" diff --git a/sbin/run_args.sh b/sbin/run_args.sh new file mode 100755 index 0000000..44dc51d --- /dev/null +++ b/sbin/run_args.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# run_args.sh - Run command from a given file +# +( + # Run in a subshell so -e only applies to the commands in parantheses + set -e + CMD_FILE="${1:?Args file not passed to run_args.sh}" + if ! [[ -r "$CMD_FILE" ]]; then + echo "run_args.sh: Args file: '$CMD_FILE' not found" + fi + mapfile -t CMD < "$CMD_FILE" + # remove the file since we don't need it anymore + rm -f "$CMD_FILE" || : + # Finally run the command + "${CMD[@]}" +) +# Since this script is not running with -e the command below will always run +systemctl exit $? +# Exit with 0 so systemd doesn't think the service had failed +exit 0 diff --git a/systemd/export-environment.service b/systemd/export-environment.service deleted file mode 100644 index bc71e1f..0000000 --- a/systemd/export-environment.service +++ /dev/null @@ -1,9 +0,0 @@ -[Unit] -Description=Copy environment from PID 1 to a well known location - -[Service] -Type=oneshot -ExecStart=/sbin/export_environment /etc/ci-container.environment - -[Install] -WantedBy=multi-user.target