简体   繁体   中英

Start a service inside docker CentOS 7 container

I want to start the httpd service on a CentOS 7 container. But the systemctl command doesn't work in containers. In CentOS 6 I can start httpd by simply using the /etc/init.d/apachectl -d command. But in CentOS 7 I can't find any apachectl file in /*/systemd/ .

So how can I start httpd service in CentOS 7 container?

The best way is to make your own centos7 image where you install httpd

FROM centos:7
RUN yum -y install httpd; yum clean all; systemctl enable httpd.service
EXPOSE 80

Build your image with docker build -t my-centos:7 . Systemd cannot run without SYS_ADMIN. That's why I set the following vars.

$ docker run -it -p 80:80 -e "container=docker" --privileged=true -d --security-opt seccomp:unconfined --cap-add=SYS_ADMIN -v /sys/fs/cgroup:/sys/fs/cgroup:ro my-centos:7 bash -c "/usr/sbin/init"

Verify container is running:

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
967581bdf31a        my-centos:7         "bash -c /usr/sbin/in"   1 seconds ago       Up 1 seconds        0.0.0.0:80->80/tcp   gigantic_stallman

Verifiy httpd is started

$ docker exec -it gigantic_stallman /bin/bash -c "systemctl status httpd"
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
   Active: active (running) since Wed 2016-12-28 11:44:04 UTC; 2min 20s ago
     Docs: man:httpd(8)
           man:apachectl(8)
 Main PID: 61 (httpd)
   Status: "Total requests: 0; Current requests/sec: 0; Current traffic:   0 B/sec"
   CGroup: /docker/967581bdf31a3b741a5e857720e199614d816b05a2132271f3adf910f0ed3207/system.slice/httpd.service
           ├─61 /usr/sbin/httpd -DFOREGROUND
           ├─66 /usr/sbin/httpd -DFOREGROUND
           ├─67 /usr/sbin/httpd -DFOREGROUND
           ├─68 /usr/sbin/httpd -DFOREGROUND
           ├─69 /usr/sbin/httpd -DFOREGROUND
           └─70 /usr/sbin/httpd -DFOREGROUND

Dec 28 11:44:04 967581bdf31a systemd[1]: Starting The Apache HTTP Server...
Dec 28 11:44:04 967581bdf31a httpd[61]: AH00558: httpd: Could not reliably d...e
Dec 28 11:44:04 967581bdf31a systemd[1]: Started The Apache HTTP Server.

Run the docker pull command to download the Docker image, including Apache named httpd.

#docker pull httpd 

Check the docker images using

#docker images 

Now run the docker command to invoke the image you downloaded.

#docker run -d --name docker-apache -p 80:80 -d httpd

Mapping the local computer's port 80 to the container's port 80 (-p 80:80). Try to verify whether the apache web server is working by accessing the server IP or hostname in the browser.

TL;DR: For short answer please see the other author's Answer.

My question was wrong here because it doesn't align with the containerization philosophy IMO. As these kinds of questions would be asked by new user I am going to explain a few things that's indirectly related to this question.

What is a container?

From OCI's runtime Specification , approximately,

  1. A container contains the unit of a deliverable software.
  2. A container will encapsulate a software component and it's dependencies.
  3. A container should be portable and platform agnostic.

And one of the major component to achieve containerization is container runtime or in general linux container . Container runtime is a piece of software that is responsible for running containers.

Examples of a few container runtimes are, containerd , docker-engine , crio , mcr etc.

Why the question is wrong?

In general and by design, a linux container is an isolated process (these days virtual machines are also considered as containers ). So in an ideal situation we should create a container just with one process which is our deliverable software.

In the question, I was thinking of using systemd to manage the process inside the container because I was neither aware about difference between a virtual machine and a container nor the principles of OCI's specification.

Also, systemd or systemV is system management daemon that is required to manage systems with hundreds or thousands of process. As the desired number of process in a container is only one so we do not need a process management daemon or any other unnecessary tools like ssh , htop , net-tools , firewalld etc.

How do we run the deliverable software?

The ideal way to run an application inside the container is to use it as the container's Entrypoint or CMD . That means, when we run the container, it will try to initiate the Entrypoint and it will start it with default command defined in the CMD . Either way, the first process (PID 1) should be our desired application/software.

So when we build the container image, we should define the entrypoint of that container. For example, I have an httpd and a redis container.

╰──➤ docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS      NAMES
23789e2d0416   redis     "docker-entrypoint.s…"   36 seconds ago   Up 35 seconds   6379/tcp   elegant_ganguly
9be725968ff3   httpd     "httpd-foreground"       14 minutes ago   Up 14 minutes   80/tcp     app1

So let's check the first process of the both containers ( cat /proc/1/cmdline ),

╰──➤ for i in $(docker ps -q); do docker inspect $i --format 'ImageName: {{.Config.Image}}'; printf "First PID: "; docker exec -i $i sh -c "cat /proc/1/cmdline";echo; done

ImageName: redis
First PID: redis-server *:6379
ImageName: httpd
First PID: httpd-DFOREGROUND

Let's try to see the same thing with ps

╰──➤ for i in $(docker ps -q); do docker inspect $i --format 'ImageName: {{.Config.Image}}'; docker run -i --rm --pid container:$i ubuntu sh -c "ps aux | head -n2"; done
ImageName: redis
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
999          1  0.4  0.0  56024  7760 ?        Ssl  14:58   0:08 redis-server *:6379
ImageName: httpd
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0   7300  4380 ?        Ss   14:44   0:00 httpd -DFOREGROUND

So if we are using these images; majority of the time we do not need to start it separately because it's probably already invoked by the entrypoint.

But if we want to create our own container image for our own software we can do that just by mentioning the entrypoint like the both of the httpd and redis image did here and here . You can also use CMD and Entrypoint from the command line when you run the container with the help of --entrypoint or provide the command after container name like the following (here I am using while true; do date; sleep 1; done as the default CMD ),

╰──➤ docker run -d --rm ubuntu sh -c "while true; do date; sleep 1; done"
35c6352a55f25335e1bd0874493f2a31155ef752d008eb6718923d1f04ab2c14

Now let's check the first PID,

╰──➤ docker run -i --rm --pid container:35c6352a55f25 ubuntu sh -c "ps aux | head -n2"      
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0   2308   832 ?        Ss   15:42   0:00 sh -c while true; do date; sleep 1; done

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM