Tabla de contenido
En este artículo explicaremos cómo crear un contenedor que soporte systemd con docker ya que es un tema bastante curioso.
Lo primero, ¿Qué es systemd?
Como dice en su web oficial:
systemd es un conjunto de bloques de construcción básicos para un sistema Linux. Proporciona un administrador de sistemas y servicios que se ejecuta como PID 1 e inicia el resto del sistema.
Puedes ver como crear un servicio en systemd pinchando aquí
¿Está bien usar systemd en un contenedor docker?
Siempre que se utilice en un entorno local o de desarrollo no hay ningún problema, pero no es algo que yo recomiende para un servidor de producción siempre y cuando existan otras alternativas.
¿Por qué usar un contenedor docker que use systemd?
En ocasiones necesitamos hacer pruebas con una aplicación que utiliza systemd en vez de sysvinit, si queremos hacer las pruebas en un entorno basado en docker por defecto no podemos ya que requiere que que es sistema donde se ejecuta sea capaz de instalar servicios de systemd.
También nos puede venir bien de cara a simular un sistema mas completo pero sin consumir tantos recursos como una virtualización.
Creand el contenedor con systemd incluido
En un contenedor con una imagen de CentOS no es necesario crear el dockerfile para crear una imagen con systemd incluido ya que por defecto viene incluido en la imagen y solo debemos levantarlo con la sentencia docker run que enseñaremos mas tarde.
Para ubuntu crearemos el siguiente dockerfile para incluir soporte de systemd, crearemos un fichero llamado «ubuntu-systemd-dockerfile»:
FROM ubuntu:latest #BASE INSTALL RUN export DEBIAN_FRONTEND=noninteractive;ln -fs /usr/share/zoneinfo/America/New_York /etc/localtime;apt-get update && apt-get install tzdata && apt-get install -y vim autotools-dev dosfstools libmailtools-perl kmod net-tools apt-utils bind9utils binutils bsdmainutils bsdutils coreutils debianutils diffutils dnsutils docutils-common docutils-doc findutils iputils-ping iputils-tracepath klibc-utils libkeyutils1:amd64 libpaper-utils sensible-utils sysvinit-utils xz-utils systemd systemd-sysv RUN ln -f /usr/bin/systemd /sbin/init ## for apt to be noninteractive ENV DEBIAN_FRONTEND noninteractive ENV DEBCONF_NONINTERACTIVE_SEEN true STOPSIGNAL SIGRTMIN+3 CMD [ "/sbin/init" ]
Para crear la imagen ubuntu:systemd tenemos que ejecutar la siguiente sentencia desde el mismo directorio donde tenemos el fichero Dockerfile con nombre ubuntu-systemd-dockerfile que hemos creado:
docker build -f Dockerfile -t "ubuntu:systemd" .
Lo haremos como se puede ver en:
root@ger:/tmp# mkdir ubuntu-systemd root@ger:/tmp# cd ubuntu-systemd/ root@ger:/tmp/ubuntu-systemd# vi ubuntu-systemd-dockerfile root@ger:/tmp/ubuntu-systemd# docker build -f ubuntu-systemd-dockerfile -t "ubuntu:systemd" . Sending build context to Docker daemon 2.56kB Step 1/7 : FROM ubuntu:latest ---> 1e4467b07108 Step 2/7 : RUN export DEBIAN_FRONTEND=noninteractive;ln -fs /usr/share/zoneinfo/America/New_York /etc/localtime;apt-get update && apt-get install tzdata && apt-get install -y vim autotools-dev dosfstools libmailtools-perl kmod net-tools apt-utils bind9utils binutils bsdmainutils bsdutils coreutils debianutils diffutils dnsutils docutils-common docutils-doc findutils iputils-ping iputils-tracepath klibc-utils libkeyutils1:amd64 libpaper-utils sensible-utils sysvinit-utils xz-utils systemd systemd-sysv ---> Using cache ---> 27e6132e5c37 Step 3/7 : RUN ln -f /usr/bin/systemd /sbin/init ---> Using cache ---> 0e1242818129 Step 4/7 : ENV DEBIAN_FRONTEND noninteractive ---> Using cache ---> ad16907c6036 Step 5/7 : ENV DEBCONF_NONINTERACTIVE_SEEN true ---> Using cache ---> 6c27cc829879 Step 6/7 : STOPSIGNAL SIGRTMIN+3 ---> Using cache ---> 2fc7405c18d1 Step 7/7 : CMD [ "/sbin/init" ] ---> Using cache ---> 5ba555ffd849 Successfully built 5ba555ffd849 Successfully tagged ubuntu:systemd root@ger:/tmp/ubuntu-systemd#
Una vez creada la imagen ubuntu:systemd podemos ejecutar la siguiente sentencia para crear el contenedor:
docker run -it -d --tmpfs=/run --tmpfs=/run/lock -v /sys/fs/cgroup:/sys/fs/cgroup:ro --name mitest --hostname mitest ubuntu:systemd /sbin/init
Este es un ejemplo de la ejecución anterior:
root@ger:/tmp/ubuntu-systemd# docker run -it -d --tmpfs=/run --tmpfs=/run/lock -v /sys/fs/cgroup:/sys/fs/cgroup:ro --name mitest --hostname mitest centos /sbin/init 243f2021ec3921aad4f34bc05eac034d91143f4ad2a3bc61fc47ad136370c3be root@ger:/tmp/ubuntu-systemd# docker exec -it mitest su - [root@mitest ~]# systemctl |more UNIT LOAD ACTIVE SUB DESCRIPTION -.mount loaded active mounted / dev-mqueue.mount loaded active mounted POSIX Message Queue File System etc-hostname.mount loaded active mounted /etc/hostname etc-hosts.mount loaded active mounted /etc/hosts etc-resolv.conf.mount loaded active mounted /etc/resolv.conf proc-acpi.mount loaded active mounted /proc/acpi proc-asound.mount loaded active mounted /proc/asound proc-bus.mount loaded active mounted /proc/bus proc-fs.mount loaded active mounted /proc/fs proc-irq.mount loaded active mounted /proc/irq proc-kcore.mount loaded active mounted /proc/kcore proc-keys.mount loaded active mounted /proc/keys proc-sched_debug.mount loaded active mounted /proc/sched_debug proc-scsi.mount loaded active mounted /proc/scsi proc-sysrq\x2dtrigger.mount loaded active mounted /proc/sysrq-trigger proc-timer_list.mount loaded active mounted /proc/timer_list run-lock.mount loaded active mounted /run/lock sys-firmware.mount loaded active mounted /sys/firmware ● sys-fs-fuse-connections.mount loaded failed failed FUSE Control File System systemd-ask-password-console.path loaded active waiting Dispatch Password Requests to Console Directory Watch systemd-ask-password-wall.path loaded active waiting Forward Password Requests to Wall Directory Watch session-c1.scope loaded active running Session c1 of user root dbus.service loaded active running D-Bus System Message Bus systemd-hwdb-update.service loaded active exited Rebuild Hardware Database systemd-journal-catalog-update.service loaded active exited Rebuild Journal Catalog systemd-journal-flush.service loaded active exited Flush Journal to Persistent Storage systemd-journald.service loaded active running Journal Service systemd-logind.service loaded active running Login Service systemd-random-seed.service loaded active exited Load/Save Random Seed systemd-readahead-collect.service loaded active exited Collect Read-Ahead Data systemd-tmpfiles-setup.service loaded active exited Create Volatile Files and Directories systemd-update-done.service loaded active exited Update is Completed systemd-update-utmp.service loaded active exited Update UTMP about System Boot/Shutdown systemd-user-sessions.service loaded active exited Permit User Sessions -.slice loaded active active Root Slice system-getty.slice loaded active active system-getty.slice system.slice loaded active active System Slice user-0.slice loaded active active User Slice of root [root@mitest ~]#
Crear un contenedor basado en CentOS con soporte para systemd
Como decíamos antes, si necesitamos crear un contenedor basado en CentOS o en otra imagen que ya incluya soporte para systemd no es necesario hacer el proceso anterior, solo debemos ejecutar:
docker run -it -d --tmpfs=/run --tmpfs=/run/lock -v /sys/fs/cgroup:/sys/fs/cgroup:ro --name mitest --hostname mitest centos /sbin/init
Como se puede ver a continuación:
root@ger:/tmp/ubuntu-systemd# docker run -it -d --tmpfs=/run --tmpfs=/run/lock -v /sys/fs/cgroup:/sys/fs/cgroup:ro --name mitest2 --hostname mitest2 centos /sbin/init 00ebdd7192062fe15b54b9a6ae7ed5eae979b1560a3dd82127f8fe9dc30afa43 root@ger:/tmp/ubuntu-systemd# docker exec -it mitest2 su - [root@mitest2 ~]# systemctl|more UNIT LOAD ACTIVE SUB DESCRIPTION -.mount loaded active mounted / dev-mqueue.mount loaded active mounted POSIX Message Queue File System etc-hostname.mount loaded active mounted /etc/hostname etc-hosts.mount loaded active mounted /etc/hosts etc-resolv.conf.mount loaded active mounted /etc/resolv.conf proc-acpi.mount loaded active mounted /proc/acpi proc-asound.mount loaded active mounted /proc/asound proc-bus.mount loaded active mounted /proc/bus proc-fs.mount loaded active mounted /proc/fs
Se pueden ver mas parámetros interesantes en la documentación oficial de docker pinchando aquí