Any simple and safe way to start services on CentOS7 / systemd?

$ docker run -ti centos:centos7 bash
# yum update && yum install -y httpd initscripts

I don’t really want to use CentOS7 or systemd, my service runs fine in CentOS6, but I need to use “overlay” to workaround an aufs bug, and overlay is only compatible with latest centos 7.2.

# service httpd start
Redirecting to /bin/systemctl start  httpd.service
Failed to get D-Bus connection: Operation not permitted

In my case it’s a custom rpm and service I’m installing, but it looks like the same error I get with httpd.

I see this suggestion to run --privileged -e "container=docker" -v /sys/fs/cgroup:/sys/fs/cgroup then run /usr/sbin/init:

But I’m hoping there is a simpler solution that doesn’t require privileged or init. In my working CentOS6 image I just “service start myservice” then tail the log.

Is there a Fedora(?) distribution that is compatible with “overlay” while not using systemd? Any other suggestions?

Thanks,
Jamshid

1 Like

Did you ever get an answer to this? have similar issue. But when I ran with the suggestion it rebooted /killed the VM I was running in.

I’m somewhat confused by the issue – if you need to use overlay then CentOS 7 will need to be used on the host, but inside of the container you should be able to run whatever you want (you can even run debian based images on RH distros if only the userspace pieces change).

So, if your image was based on 6 before, it should be perfectly fine to keep using that same image. If you can do that, I say go for it.

That said, instead of running things like service start in a container, usually ENTRYPOINT just invokes the process directly (example from the official images), maybe with a small wrapper startup script. So, it might be worth cracking open the systemd service file and just running what it ends up running anyway (ExecStart I think?) as the entrypoint of the container instead of using systemd in the container.

Most of the things systemd usually takes care of (e.g. restarts and service dependencies) should be happening outside of the container anyway, either through the host’s systemd, or your container orchestrator, etc.

CentOS6 yum in a container has a weird problem on docker with overlay:


Btw running yum --rebuilddb before every yum install is a usable workaround.

Yes, ideally I wouldn’t use “service” but in this case I’m trying to test an existing service, including its startup script as if on a “real” system.

Well for me I’m still in learning mode WRT Docker and I know my example is not something you would normally do but what I have been trying to do is start a telnet server (I know I know use ssh, but this is a experiment) in a container. by problem is after installing hthe telnet-server rpm I need to start the service on centos 7 and you do that generally I understand with :slight_smile:

systemctl restart /usr/lib/systemd/system/telnet.socket well I get this when I build the Dockerfile
Failed to get D-Bus connection: Operation not permitted

The above was listed on the net as a way to get past that error. but I guess because it’s overlaying init it overlays by existing VM login session with this new container. Not what I was shooting for.

Mainly what I was looking to show was if you log into a container you don’t see much WRT processes, etc. Looking to show that if you connect via a network socket and compromise it you really don’t see anything from the host OS.

@macedemo

You don’t need to run systemd inside of the container in order to do this. Daemons run in containers should be invoked directly as an ENTRYPOINT.

After installation with yum install -y telnet-server, you can see a systemd service file indicating how the server is meant to be run at /usr/lib/systemd/system/telnet@.service.

[root@baf4029d2be6 /]# cat "/usr/lib/systemd/system/telnet@.service"
[Unit]
Description=Telnet Server
After=local-fs.target

[Service]
ExecStart=-/usr/sbin/in.telnetd
StandardInput=socket

You could invoke /usr/sbin/in.telnetd directly (although it looks like the dep on systemd is more hardcoded than I initially thought, relying on socket activation etc.).

There is also instructions for “Running a systemd based service” at https://hub.docker.com/_/centos/. Did you try them? I’m able to get a working telnet server running in systemd in a container fine by following the instructions there (including making the temporary bind mount dir as suggested by comments). The authentication fails when attempting a telnet, but I can clearly see the process running, so it merely needs to be configured to accept connections properly.

@jamshid Ah, unfortunate to hear about the overlay bug.

Did you try the instructions on the CentOS Docker Hub page linked above to see if they will work for running the service? They do require a few bind mounts, but not --privileged.

Yes, thanks, using instructions from hub does seem to work, at least with docker 1.11.0 on aufs. Here’s a complete working example.

Put this Dockerfile in a directory:

# This shows systemd services (nginx and named) running in a centos7 container.
# There have been lots of problems and workarounds for this, see:
# https://hub.docker.com/_/centos/
# https://github.com/docker/docker/issues/7459

FROM centos:centos7

RUN yum install -y epel-release # for nginx
RUN yum install -y initscripts  # for old "service"

ENV container=docker

RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*;

# named (dns server) service
RUN yum install -y bind bind-utils
RUN systemctl enable named.service 

# Unrelated to systemd, but Apacehe httpd install fails at least if docker uses
# (default) aufs.
#   Error unpacking rpm package httpd-2.4.6-40.el7.centos.x86_64
#   error: unpacking of archive failed on file /usr/sbin/suexec: cpio: cap_set_file
#RUN yum install -y httpd

# webserver service
RUN yum install -y nginx
RUN systemctl enable nginx.service

# Without this, init won't start the enabled services and exec'ing and starting
# them reports "Failed to get D-Bus connection: Operation not permitted".
VOLUME /run /tmp

# Don't know if it's possible to run services without starting this
CMD /usr/sbin/init

And add this docker-compose.yml to the same directory:

version: '2'
services:
  test:
    build:
      context: .
    cap_add:
      - SYS_ADMIN
    security_opt:
      - seccomp:unconfined
    volumes:
      - /sys/fs/cgroup:/sys/fs/cgroup:ro
    ports:
      - "80:80"
      # The DNS server works within container (dig @localhost example.com), but
      # *not* via published port. Not sure this is related to systemd.
      #- "53:53/tcp"
      #- "53:53/udp"

Finally, run these commands to build and start the container:

docker-compose build && docker-compose down && docker-compose up -d

If there were no errors you should be able to “curl -I http://docker.local:80” (substitute your docker server) to see the nginx service is running.

1 Like

Running systemd / CentOS under docker is still painful but seems to be working again in Docker 1.12.1. You might want to follow this issue for more info:

I just wish I understand why this works:

$ docker run  -ti --cap-add SYS_ADMIN --security-opt seccomp:unconfined -p 80:80 local/c7-systemd-httpd bash -c "/usr/sbin/init"

systemd 219 running in system mode. (+PAM +AUDIT +SELINUX +IMA -APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ -LZ4 -SECCOMP +BLKID +ELFUTILS +KMOD +IDN)
Detected virtualization docker.
Detected architecture x86-64.

Welcome to CentOS Linux 7 (Core)!

Set hostname to <b0c542c67637>.
Initializing machine ID from random generator.
Running in a container, ignoring fstab device entry for /dev/disk/by-uuid/4a14fa4c-8462-4bcf-8b68-315f5db5d123.
[  OK  ] Reached target Paths.
...

but this doesn’t:

$ docker run  -ti --cap-add SYS_ADMIN --security-opt seccomp:unconfined -p 80:80 local/c7-systemd-httpd bash
[root@e0ae35935b8e /]# /usr/sbin/init 
Couldn't find an alternative telinit implementation to spawn.

Ah I figured out why running /usr/sbin/init from shell doesn’t work – you need to use the bash exec command, I guess systemd really wants to be PID 1.

# Requires docker 1.12.1, currently still beta in Docker for Mac
$ docker run  -ti --cap-add SYS_ADMIN -p 80:80 local/c7-systemd-httpd bash

[root@e0ae35935b8e /]# /usr/sbin/init 
Couldn't find an alternative telinit implementation to spawn.

[root@e0ae35935b8e /]# exec /usr/sbin/init 
systemd 219 running in system mode. (+PAM +AUDIT +SELINUX +IMA -APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ -LZ4 -SECCOMP +BLKID +ELFUTILS +KMOD +IDN)
Detected virtualization docker.
Detected architecture x86-64.

Welcome to CentOS Linux 7 (Core)!
...

It seems systemd is finally working reliably in docker, see:

docker run -it \
   --name=tmp \
   --cap-add=SYS_ADMIN \
   -e "container=docker" \
   -v /sys/fs/cgroup:/sys/fs/cgroup:ro \
   --tmpfs /run \
   --tmpfs /run/lock \
   ubuntu:16.04 /sbin/init
1 Like

Hi Jamshid,
when i ran the “sudo systemctl start docker” or “sudo dockerd &” on centos7.4 system,always got error message"Failed to get D-Bus connection: Operation not permitted",please tell me ,what can i do for this error.thanks.

@nathanleclaire
hello,
when i ran the “sudo systemctl start docker” or “sudo dockerd &” on centos7.4 system,always got error message"Failed to get D-Bus connection: Operation not permitted",please tell me ,what can i do for this error.thanks.

this works fine for me:

docker run --cap-add SYS_ADMIN -p 8080:8080 --rm -it --name centos centos:centos7.6.1810 bash

FYI the recent Docker for Desktop 4.3.0, at least on Mac, broke systemd in containers. Downgrade to 4.2.0 or wait for Unable to run systemd services on M1 / Silicon computer · Issue #6073 · docker/for-mac · GitHub to be fixed.