docker-compose を使用して、単一のサーバーで React/Node.js アプリケーションを実行しています。React アプリのダウンタイムなしのデプロイメントを実現しようとしています。現在のプロセスでは、webpack ビルド (dist フォルダー内のファイルを置き換えます) を実行し、次に docker down と docker up を実行します。このプロセス全体に約 2 ~ 3 分かかります。docker-compose を使用するとコンテナーをスケール アップ/ダウンできることはわかりましたが、コードを 1 つにプッシュして 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
これには、シンプルな単一ノードの Swarm を強くお勧めします。これは、更新中にダウンタイムをゼロにする必要があるが、マルチノードの高可用性は必要ないか、必要ない場合に最適なソリューションです。オーバーヘッドや管理上の負担はまったく追加されず、同じ構成ファイルを使用します。
はい、このサーバーに出荷する予定のコミットごとに、コードを含むイメージの新しいバージョンを実際に構築する必要があります。ツールはこのタイプのワークフローを想定しているため、このワークフローを採用すると作業が簡単になります。Docker Hub は、GitHub と BitBucket のブランチへのコミットごとにこれを実行することをサポートしています (オープンソースの場合は無料、単一のプライベート リポジトリの場合は無料)。Docker Hub で毎回新しいイメージを構築すると仮定すると、単一ノードのスウォームでの動作は次のようになります。
- 最新の安定したDockerバージョン(この記事の時点では17.12)を使用していると仮定します。
docker swarm init
これで、単一ノードのスウォームができました。これで完了です。(Dockerのものをデプロイできるサーバーが1つしかない場合は私は常にsingle-node-swarmを使用し、docker-composeを使用しない理由はいくつかあります。。- いくつかの変更を加えるだけで、コンポーズファイルをスタックファイルとして使用できます。
docker stack deploy -c compose-file.yml stackname
- ゼロダウンタイムの導入を確実にするには、ヘルスチェックを追加ノード/nginx コンテナに追加して、アプリが本当に「接続準備完了」になったことを知らせます。Swarm はサービス更新時にもこれを使用するため、これは重要です。
- 古いコンテナを削除する前に、Swarmに新しいコンテナを追加したい場合は、以下を追加します。
order: start-first
古いコンテナを削除する前に、Swarmにhttps://docs.docker.com/compose/compose-file/#update_config。 - 次に、compose ファイル内のイメージ タグを変更し、同じスタック デプロイ コマンドを再度実行する
myuser/myrepo:1.0
とmyuser/myrepo:2.0
、Swarm は違いを検出し、新しいイメージでサービスを更新します (コンテナーを置き換えます)。
これをテストするには、httping を使用して、更新プロセス中にリモートで引き続き利用可能であることを確認します。