重启后按特定顺序启动Docker容器

8

背景

我的大部分Docker容器都是运行在80端口上的Web应用程序。为了让它们都运行在单个主机上,我允许Docker分配一个随机未使用的端口,并使用 jwilder/nginx-proxy (参考链接) 作为反向代理。这需要在容器启动之前先运行jwilder/nginx-proxy,在构建完成后运行容器的bash脚本中很容易实现:

...
#######################
# ensure that we are running the frontend proxy 
# which allows us to run multiple web containers
RESULT=`docker ps | grep jwilder | wc -l`

if [ $RESULT -gt 0 ];then
    echo "found frontend proxy."
else
    echo "Deploying frontend proxy"
    docker run -d \
    -p 80:80 \
    -v /var/run/docker.sock:/tmp/docker.sock \
    -t jwilder/nginx-proxy
fi
#######################


# Now start the container.
docker run -d \
-e VIRTUAL_HOST=$VIRTUAL_HOST \
-p 80 \
-p 443 \
--name="$PROJECT_NAME" \
$CONTAINER_IMAGE

问题

我经常需要重新启动我的服务器,我需要一个解决方案,可以自动并按正确顺序启动所有容器。

我可以使用docker run参数--restart=always,在重启后使所有正在运行的容器自动启动,但是,如何确保我的反向代理容器首先启动,然后在任何其他容器启动之前有短暂的延迟(以任何顺序)。

理想情况下,我希望有一个解决方案,不依赖于特定的发行版,例如使用supervisord而不是编写upstart或systemd启动脚本,但我需要一种方法来连接到在docker守护程序成功启动后触发的方式。

1个回答

6
如果您将所有带有Web应用程序的容器上的端口80公开,则可以将它们链接到您的Nginx容器。以下是一个小的docker-compose.yml示例:
app:
    build: app/
    expose:
        - "80"

api:
    build: api/
    expose:
        - "80"

webserver:
    image: nginx
    ports:
        - "80:80"
    volumes:
        - default.conf:/etc/nginx/conf.d/default.conf
    links:
        - app
        - api

这里是Nginx的配置:

server {
    listen       80;
    server_name  localhost;

    location / {
        proxy_pass http://app;
    }

    location /api {
        proxy_pass http://api;
    }
}

upstream app {
    server app:80;
}

upstream api {
    server api:80;
}

当您将一个容器链接到另一个容器(在本例中是Nginx),Docker会更改/etc/hosts文件,并添加如下行:

172.17.0.7 api 165637cfd4ab yourproject_api_1

172.17.0.5 app dedf870dec53 yourproject_app_1

这样Nginx就知道了api和app容器的存在。
当请求到达'localhost:80'时,Nginx将其代理到http://app:80hosts将请求解析为htt://app,并转发到app容器的172.17.0.7地址。
使用$ docker-compose up启动所有容器即可完成设置。

我认为这对我行不通,因为我需要能够动态部署任意数量的Web应用程序,所有这些应用程序都需要这个单一共享的反向代理,而不是每个应用程序都自己启动反向代理。我不知道每个服务器上会有多少Web应用程序,也可能会将它们移动到其他地方。此外,Docker Compose是否会自动确保在重新启动时链接到的反向代理会启动?也许您正在依赖另一个脚本来确定Docker是否已经运行并调用“docker-compose up”? - Programster
Programster: 在Docker启动与链接的容器之前,它将先启动一个容器,因此这种方法似乎是有意义的。您只需在启动容器时指定--link proxy:proxy即可。 - Adrian Mouat
@AdrianMouat 我的每个Web应用程序可以基本上使用相同的Compose文件,第一个应用程序启动后,对其他Compose文件的后续调用将意识到反向代理已经启动并使用它吗?我的Web应用程序独立/随机地部署在多个主机上,但如果主机上已经运行反向代理,则需要共享该代理,并且仅在不存在代理时才部署它。 - Programster
我想我建议不要使用compose,而是仍然使用--link技巧来确保容器重新启动时的顺序。 - Adrian Mouat
还有更多的解决方案,比如systemd和ansible。如果你使用systemd,就不能使用--restart选项。如果你想走这条路,请参考http://container-solutions.com/2015/04/running-docker-containers-with-systemd/。 - Adrian Mouat
事实证明,我的假设是错误的。反向代理在 Web 应用程序之前不需要运行,因此您可以在启动反向代理和容器本身的 bash 脚本中添加 restart=always。由于某种原因,我的一些容器在启动时无法启动 apache,因此我将研究在容器内使用 supervisord 以确保 apache 正在运行。 - Programster

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接