Docker 容器中应用程序的常用开机动作

阅读时长 6 分钟读完

在 Docker 容器中,我们经常需要在容器启动后自动执行一些开机动作,例如启动服务、部署代码、备份数据等等。本文将介绍 Docker 容器中常用的开机动作,并提供详细的示例代码供读者参考学习。

1. 使用 CMD 命令启动应用程序

在 Dockerfile 中,我们可以通过 CMD 命令来指定容器启动时要执行的默认命令。例如,以下 Dockerfile 指定启动一个 Node.js 应用程序,并监听 3000 端口:

在这个 Dockerfile 中,CMD ["npm", "start"] 指定了容器启动后要执行的命令,即在 /app 目录下运行 npm start 命令启动 Node.js 应用程序。EXPOSE 3000 则指定了容器运行时暴露的端口。

2. 使用 ENTRYPOINT 命令启动应用程序

除了使用 CMD 命令外,我们还可以使用 ENTRYPOINT 命令来指定容器启动时要执行的默认命令。与 CMD 命令不同的是,ENTRYPOINT 命令会将容器启动时传入的参数作为其参数,因此可以通过传入参数来修改启动命令。以下是一个使用 ENTRYPOINT 命令启动 Python 应用程序的 Dockerfile 示例:

在这个 Dockerfile 中,ENTRYPOINT [ "python", "./entrypoint.py" ] 指定了容器启动后要执行的命令,即使用 Python 解释器运行 entrypoint.py 文件。如果我们需要传入其他参数以修改启动命令,可以直接在 docker run 命令中指定参数,例如:

这样,在运行容器时就会将 arg1 与 arg2 作为参数传递给 entrypoint.py。

3. 使用 supervisord 管理多个进程

在有些情况下,我们需要在同一个容器中运行多个进程,例如同时运行 Web 服务器和消息队列等。这时,我们可以使用 supervisord 进程管理工具来管理多个进程。以下是一个使用 supervisord 启动 Flask 和 Celery 任务队列的 Dockerfile 示例:

在这个 Dockerfile 中,使用 apt-get 命令安装了 supervisord 进程管理工具,并将 supervisord.conf 文件复制到了容器中。supervisord.conf 文件中配置了两个进程:

-- -------------------- ---- -------
-------------
-------------

-------------
-------------- --------
--------------
--------------
----------------
-------------------------------
-------------------------------

----------------
-------------- -- ---------- ------ ----------------
--------------
--------------
----------------
----------------------------------
----------------------------------
展开代码

在这个配置中,program:web 配置了一个名为 web 的进程,它会在 /app 目录下启动一个 Flask 应用程序。program:worker 则配置了一个名为 worker 的进程,它会在 /app 目录下启动一个 Celery 任务队列。由于 nodaemon=true,因此 supervisord 不会在前台运行,而是以守护进程的方式运行。CMD ["/usr/bin/supervisord"] 则指定了容器启动后要运行 supervisord。

4. 使用 Tini 来规避 PID 1 问题

在 Docker 容器中,如果默认启动的进程意外退出,Docker 引擎会尝试将容器停止下来。但是,如果默认启动的进程是一个复杂的进程管理工具,例如 supervisord,当其中任意一个子进程意外退出时,Docker 引擎就无法停止容器。因此,我们需要使用 Tini 来规避 PID 1 问题。Tini 是一个类似 init 的进程,它能够安全地终止子进程,并能够将 SIGTERM 信号正确地传递给默认启动的进程。以下是一个使用 Tini 启动 Node.js 应用程序的 Dockerfile 示例:

在这个 Dockerfile 中,ENTRYPOINT [ "/usr/bin/tini", "--" ] 指定了容器启动时要执行的命令,即使用 Tini 启动容器中的进程。CMD ["npm", "start"] 则是默认启动的进程,即在 /app 目录下运行 npm start 命令启动 Node.js 应用程序。EXPOSE 3000 则指定了容器运行时暴露的端口。

5. 使用 init.d 脚本启动服务

在一些企业级应用中,服务启动脚本通常是一个 init.d 脚本,例如在 CentOS 系统下的服务。在 Docker 容器中,我们可以通过在容器中运行 init 进程,再由 init 进程启动 init.d 脚本来启动服务。以下是一个使用 init.d 脚本启动 Nginx 服务器的 Dockerfile 示例:

在这个 Dockerfile 中,首先安装了 Nginx 服务器。然后,将 daemon off; 修改为 daemon off;\n,以避免 Nginx 在前台运行并占用 Docker 容器进程。接着,将 nginx 脚本复制到 /etc/init.d/nginx 目录下,并将其设置为可执行。CMD ["service", "nginx", "start"] 指定了容器启动时执行的命令,即启动 Nginx 服务器。EXPOSE 80 则指定了容器运行时要暴露的端口。

通过这样的方式,我们就能在 Docker 容器中启动 init.d 脚本,并成功启动服务。

结语

在 Docker 容器中,有多种方式可以指定容器启动后默认执行的命令。本文介绍了 Docker 容器中常用的开机动作,并提供了详细的示例代码供读者参考学习。在实际开发中,我们可以根据应用程序的需要选择适合的方式来启动应用程序。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67c15e48314edc2684963813

纠错
反馈

纠错反馈