Cómo crear un contenedor que soporte systemd con docker

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í

Si estás interesado en aprender Docker puedes puedes adquirir nuestro libro aquí.

Docker para novatos

Docker para novatos - Gerardo G. Urtiaga-portada-web

Deja una respuesta