我有一个使用 docker-compose 在单个服务器上运行的 React/Node.js 应用程序。我正在尝试实现 React 应用程序的零停机时间部署。现在的过程是进行 webpack 构建(替换 dist 文件夹中的文件),然后执行 docker down 和 docker up。整个过程大约需要 2-3 分钟。我意识到使用 docker-compose 可以扩大/缩小容器,但我不知道如何仅将代码推送到其中一个并重建 webpack。我真的不想使用 Kubernetes/Swarm 或 Openshift,因为它有点过头了。我想知道是否有其他人实现了类似的目标。
我的docker-compose看起来像这样:
node:
build:
context: ./env/docker/node
args:
- PROJECT_ROOT=/var/www/app
image: react_app:rapp_node
command: "npm run prod"
expose:
- "3333"
networks:
- react-net
volumes_from:
- volumes_source
tty: false
nginx:
env_file:
- ".env"
build:
context: ./env/docker/nginx
volumes_from:
- volumes_source
volumes:
- ./env/data/logs/nginx/:/var/log/nginx
- ./env/docker/nginx/sites/node.template:/etc/nginx/node.template
networks:
- react-net
- nginx-proxy
environment:
NGINX_HOST: ${NGINX_HOST}
VIRTUAL_HOST: ${NGINX_VIRTUAL_HOST}
LETSENCRYPT_HOST: ${NGINX_VIRTUAL_HOST}
ESC: $$
links:
- node:node
command: /bin/sh -c "envsubst < /etc/nginx/node.template > /etc/nginx/sites-available/node.conf && nginx -g 'daemon off;'"
volumes_source:
image: tianon/true
volumes:
- ./app:/var/www/app
我的 nginx 是这样的:
server {
server_name www.${NGINX_HOST};
return 301 ${ESC}scheme://${NGINX_HOST}${ESC}request_uri;
}
server {
listen 80;
server_name ${NGINX_HOST};
root /var/www/app;
location / {
proxy_pass http://node:3333;
proxy_http_version 1.1;
proxy_set_header Upgrade ${ESC}http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host ${ESC}host;
proxy_cache_bypass ${ESC}http_upgrade;
}
}
答案1
我认为更好的方法是使用任何编排器,它们都支持滚动更新,并且您可以使用任何标准更新流程。
但是,如果你想要的正是你所写的内容(但这不是正确的方法根本),例如,您可以在容器中运行一个脚本,它将检出应用程序的新版本,构建它并将符号链接从旧版本切换到新版本,您可以像这样原子地执行此操作:ln -s new current_tmp && mv -Tf current_tmp current
。
因此,目录结构将是这样的:
/var/www/app - symlink to your current version /var/www/app_v1 - directory with current version, which symlinked to "/var/www/app" /var/www/app_v2 - directory with new version
所以现在,您可以运行命令ln -s /var/www/app_v2 /var/www/app_v2_sym && mv -Tf /var/www/app_v2_sym /var/www/app
来切换 Nginx 使用的应用程序的当前版本。
答案2
我强烈推荐一个简单的单节点集群。如果您需要在更新期间实现零停机时间,但无法或不需要多节点高可用性,那么这是一个完美的解决方案。它确实不会增加开销或更多的管理负担,并且使用相同的撰写文件。
是的,您确实应该在计划发送到此服务器的每次提交中都使用代码构建新版本的映像。这些工具需要这种类型的工作流程,因此如果您采用该工作流程,您将会更轻松。Docker Hub 支持在每次提交到 GitHub 和 BitBucket 的分支时为您执行此操作(如果是开源则免费,对于单个私有存储库仍然免费)。假设您每次都在 Docker Hub 上构建新映像,它在单节点群中的工作方式如下:
- 假设你使用的是最新的稳定 docker 版本(本文发布时为 17.12)
docker swarm init
现在您有一个单节点集群。就是这样。(如果我只能在一台服务器上部署 docker 东西我总是使用单节点集群而不是 docker-compose,原因如下。- 经过一些更改,您的 Compose 文件可以用作以下堆栈文件:
docker stack deploy -c compose-file.yml stackname
- 为了确保零停机部署,您需要添加健康检查到您的节点/nginx 容器,以便它们知道应用程序何时真正“准备好连接”。 Swarm 在服务更新期间也会使用它,因此它很关键。
- 如果你希望 Swarm 首先添加一个新容器,在移除旧容器之前,请将其添加
order: start-first
到https://docs.docker.com/compose/compose-file/#update_config。 - 然后只需在撰写文件中更改图像标签,然后
myuser/myrepo:1.0
再次myuser/myrepo:2.0
运行相同的堆栈部署命令,Swarm 将检测差异并使用新图像更新服务(通过替换容器)。
为了测试这一点,请使用 httping 来验证它在更新过程中仍然可以远程使用。