在Docker CentOS 7容器内启动服务

afdcj2ne  于 2023-01-25  发布在  Docker
关注(0)|答案(3)|浏览(161)

我想在CentOS 7容器上启动httpd服务,但是systemctl命令在容器中不起作用。在CentOS 6中,我可以简单地使用/etc/init.d/apachectl -d命令启动httpd。但是在CentOS 7中,我在/*/systemd/中找不到任何apachectl文件。
那么如何在CentOS 7容器中启动httpd服务?

p8h8hvxi

p8h8hvxi1#

最好的方法是在安装httpd的地方创建自己的centos7映像

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

使用docker build -t my-centos:7 .构建映像没有SYS_ADMIN,Systemd无法运行。这就是我设置以下变量的原因。

$ 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"

验证container是否正在运行:

$ 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

验证httpd是否已启动

$ 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.
qlzsbp2j

qlzsbp2j2#

TL;DR:简短的回答请看其他作者的回答。

***我的问题在这里是错误的***因为它不符合IMO的集装箱化理念。由于新用户会问这类问题,我将解释一些与此问题间接相关的事情。

什么是容器?

OCI's runtime Specification开始,大约,
1.容器包含可交付软件的单元。
1.容器将封装软件组件及其依赖项。
1.容器应该是可移植的并且与平台无关。
实现容器化的主要组件之一是container runtime,容器运行时是负责运行容器的软件。
一些容器运行时的例子是containerddocker-enginecriomcr等。

为什么这个问题是错的?

一般来说,linux容器是一个独立的进程(现在是virtual machines are also considered as containers),所以在理想的情况下,我们应该创建一个只有一个进程的容器,这个进程就是我们的可交付软件。
在这个问题中,我考虑使用systemd来管理容器内的进程,因为我既不知道虚拟机和容器之间的区别,也不知道OCI规范的原则。
此外,systemdsystemV是系统管理守护进程,需要管理具有数百或数千个进程的系统。由于容器中所需的进程数量只有一个,因此我们不需要进程管理守护进程或任何其他不必要的工具,如sshhtopnet-toolsfirewalld等。

如何运行可交付软件?

在容器中运行应用程序的理想方法是将其用作容器的Entrypoint or CMD。这意味着,当我们运行容器时,它将尝试初始化入口点,并使用CMD中定义的默认命令启动它。无论哪种方式,第一个进程(PID 1)都应该是我们所需的应用程序/软件。
因此,当我们构建容器映像时,我们应该定义该容器的入口点。例如,我有一个httpd和一个redis容器。

╰──➤ 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

让我们检查两个容器的第一个进程(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

让我们尝试使用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

如果我们使用这些图像大多数时候我们不需要单独启动它,因为它可能已经被入口点调用了。
但是如果我们想为我们自己的软件创建我们自己的容器映像,我们可以通过提到入口点来实现,就像httpdredis映像在这里和这里所做的那样。在--entrypoint的帮助下运行容器时,您还可以从命令行使用CMDEntrypoint,或者在容器名称后提供命令,如下面(这里我使用while true; do date; sleep 1; done作为默认CMD),

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

现在让我们检查第一个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
fhity93d

fhity93d3#

运行docker pull命令下载Docker映像,包括名为httpd的Apache。

#docker pull httpd

使用检查Docker图像

#docker images

现在运行docker命令调用下载的映像。

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

将本地计算机的端口80Map到容器的端口80(-p 80:80)。尝试通过在浏览器中访问服务器IP或主机名来验证apache Web服务器是否正在工作。


相关问题