运行Docker容器时如何自动启动服务?

How to automatically start a service when running a docker container?

我有一个Dockerfile将MySQL服务器安装在一个容器中,然后像这样开始:

1
sudo docker run -t -i 09d18b9a12be /bin/bash

但是MySQL服务不会自动启动,我必须手动运行(从容器内部):

1
service mysql start

运行docker容器时如何自动启动MySQL服务?


首先,您的Dockerfile中存在问题:

1
RUN service mysql restart && /tmp/setup.sh

Docker映像不会保存正在运行的进程。因此,您的RUN命令仅在docker build阶段执行,并在构建完成后停止。相反,当使用CMDENTRYPOINT命令启动容器时,需要指定以下命令:

1
CMD mysql start

其次,docker容器需要一个进程(最后一个命令)来保持运行,否则该容器将退出/停止。因此,常规service mysql start命令不能直接在Dockerfile中使用。

保持进程运行的三种典型方法:

  • 使用service命令并在其后附加非结束命令,例如tail -F

    1
    CMD service mysql start && tail -F /var/log/mysql/error.log

当您运行单个服务时,这通常是首选的,因为这会使docker访问输出的日志。

  • 或使用前台命令执行此操作

    1
    CMD /usr/bin/mysqld_safe

仅当存在mysqld_safe之类的脚本时,此方法才有效。

  • 或将您的脚本包装为start.sh并放在最后

    1
    CMD /start.sh

如果命令必须执行一系列步骤,这是最好的选择,同样,/start.sh应该保持运行状态。

注意

对于初学者,不建议使用supervisord。老实说,这太过分了。最好对容器使用单个服务/单个命令。

顺便说一句:请检查https://registry.hub.docker.com以获取现有的mysql docker镜像以供参考


在您的Dockerfile中,在最后一行添加

1
ENTRYPOINT service ssh restart && bash

这个对我有用

结果如下:

1
2
3
4
root@ubuntu:/home/vagrant/docker/add# docker run -i -t ubuntu
 * Restarting OpenBSD Secure Shell server sshd   [ OK ]                                                                      
root@dccc354e422e:~# service ssh status
 * sshd is running


简单!在dockerfile的末尾添加:

1
ENTRYPOINT service mysql start && /bin/bash


我一直发现还有另一种方法可以使可读性更高。

假设您要在运行它时启动rabbitmq和mongodb,那么您的CMD看起来应该像这样:

1
2
CMD /etc/init.d/rabbitmq-server start && \\
    /etc/init.d/mongod start

由于每个Dockerfile只能有一个CMD,因此窍门是将所有指令与&&串联在一起,然后对每个命令使用\\来开始新行。

如果最后添加了许多命令,我建议您将所有命令都放在脚本文件中,然后像@ larry-cai建议的那样启动它:

1
CMD /start.sh

当我想自动启动ssh服务时遇到同样的问题。
我发现将

1
/etc/init.d/ssh start

追加到

1
~/.bashrc

可以解决它,但是只有使用bash打开它才能做到。


就我而言,我有一个由Apache2提供服务的PHP Web应用程序,它在Docker容器中连接到MYSQL后端数据库。 Larry Cai的解决方案进行了少量修改。我创建了一个entrypoint.sh文件,用于管理服务。我认为在容器启动时有多个命令要执行时创建entrypoint.sh是引导docker的一种更干净的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/bin/sh

set -e

echo"Starting the mysql daemon"
service mysql start

echo"navigating to volume /var/www"
cd /var/www
echo"Creating soft link"
ln -s /opt/mysite mysite

a2enmod headers
service apache2 restart

a2ensite mysite.conf
a2dissite 000-default.conf
service apache2 reload

if [ -z"$1" ]
then
    exec"/usr/sbin/apache2 -D -foreground"
else
    exec"$1"
fi


这不起作用CMD service mysql start && /bin/bash

这不起作用CMD service mysql start ; /bin/bash ;

-我猜交互式模式不支持前台。

这有效! CMD service nginx start ; while true ; do sleep 100; done;

这有效! CMD service nginx start && tail -F /var/log/nginx/access.log

注意,您应该使用不带命令参数的docker run -p 80:80 nginx_bash


这是我在docker容器运行时自动启动MySQL服务的方式。

就我而言,我不仅需要运行MySQL,还需要运行PHP,Nginx和Memcached

我在Dockerfile中有以下几行

1
2
3
4
RUN echo"daemon off;">> /etc/nginx/nginx.conf
EXPOSE 80
EXPOSE 3306
CMD service mysql start && service php-fpm start && nginx -g 'daemon off;' && service memcached start && bash

添加&& bash将使Nginx,MySQL,PHP和Memcached在容器中运行。


我将以下代码添加到/root/.bashrc中,以仅运行一次代码,

在运行此脚本之前,请先将容器提交到映像,否则将在映像中创建" docker_services"文件,并且将不运行任何服务。

1
2
3
4
5
6
7
if [ ! -e /var/run/docker_services ]; then
    echo"Starting services"
    service mysql start
    service ssh start
    service nginx start
    touch /var/run/docker_services
fi

1
docker export -o <nameOfContainer>.tar <nameOfContainer>

可能需要使用docker prune修剪现有容器...

导入并进行必要的修改:

1
cat <nameOfContainer>.tar | docker import -c"ENTRYPOINT service mysql start && /bin/bash" - <nameOfContainer>

例如,使用始终重启选项运行容器,以确保其在主机/守护程序回收后将自动恢复:

1
docker run -d -t -i --restart always --name <nameOfContainer> <nameOfContainer> /bin/bash

边注:
在我看来,合理的做法是只启动cron服务,使容器保持尽可能干净,然后仅使用相应的检查/监视脚本修改crontab或cron.hourly,.daily等。原因是您仅依赖一个守护程序,如果发生更改,则使用ansible或puppet更容易重新分发cron脚本,而不是跟踪启动时启动的服务。


Docker网站上的以下文档显示了如何在Docker容器中实现SSH服务。它应该很容易适应您的服务:

  • https://docs.docker.com/engine/examples/running_ssh_service/

这里也有人问过这个问题:

  • 使用Docker容器自动启动sshd