一般情況下,我們專案在開發完成之後,需要部署到多套環境,比如測試、沙箱、整合等等,那麼如何通過docker-compose將node服務部署到多套環境呢?下面文章具體說下,有什麼不對的地方歡迎大家評論。
本文中的專案用到的技術是Gitlab+Ansible+Docker自動化部署node服務(nest框架寫的),步驟如下:
編寫docker-compose、docker-compose.prod.yml組態檔
修改package.json
遠端伺服器上建立兩個目錄,拉取node服務倉庫,切換到不同分支,分別表示測試、線上node服務
.gitlab-ci.yml檔案編寫
ansible.yml檔案編寫
遠端伺服器node服務(測試/線上)目錄下執行如下命令,執行之後,通過docker ps -a
檢視容器是否正常啟動,如果是up狀態掛起,證明容器啟動成功了。docker logs -f 容器id
檢視容器紀錄檔
# 測試目錄 /opt/xxx/server-test/server docker-compose up -d # 線上目錄 /opt/xxx/server-prod/server # -f表示指定具體檔案,預設執行的是docker-compose.yml檔案 docker-compose -f docker-compose.prod.yml up -d
編寫docker-compose、docker-compose.prod.yml組態檔
# docker-compose.yml version: '3.0' services: # 服務列表 # 測試資料庫 mysql: image: mysql container_name: mysql_test restart: always environment: - MYSQL_ROOT_PASSWORD=test_sql - NODE_ENV=development ports: - 13306:3306 volumes: - 伺服器上對應目錄:/var/lib/mysql # 測試node服務 server: # node服務 container_name: server-test # 容器名稱 image: node:14.15.0 ports: # 暴露的埠 - "7007:5088" environment: - NODE_ENV=development volumes: - .:/data working_dir: /data depends_on: # web服務依靠mysql要先等mysql啟動 - mysql restart: on-failure:5 # 自動重新啟動,失敗的話重新啟動5次後停止 command: yarn start # 覆蓋容器啟動後預設執行的命令
# docker-compose.prod.yml version: '3.0' services: # 服務列表 # 線上資料庫 prod-mysql: image: mysql container_name: mysql_prod restart: always environment: - MYSQL_ROOT_PASSWORD=prod_sql - NODE_ENV=production ports: - 13307:3306 volumes: - 伺服器上對應目錄:/var/lib/mysql # 線上node服務 prod-server: container_name: server-prod image: node:14.15.0 ports: - "7077:5089" environment: - NODE_ENV=production volumes: - .:/data working_dir: /data depends_on: - prod-mysql restart: on-failure:5 command: yarn start:prod
package.json中做如下修改
# cross-env指定NODE_ENV為開發或線上環境 ... "scripts": { ... "build": "nest build", "start": "yarn && cross-env NODE_ENV=development nest start", "start:prod": "yarn && yarn build && cross-env NODE_ENV=production node dist/src/main", ... }, ...
遠端伺服器上建立兩個目錄,分別存放測試、線上node服務
# 測試(dev分支),git clone node服務地址,切換到dev分支 /opt/xxx/server-test/server # 線上(master分支),git clone node服務地址,切換到master分支 /opt/xxx/server-prod/server
.gitlab-ci.yml檔案編寫
# CI變數說明說明 - BRANCH、DEV_BRANCH是CI變數,分別對應master、dev分支 - DOCKER_CONTAINER、DEV_DOCKER_CONTAINER分別對應線上、測試啟動的docker容器 - ROOT_PATH、DEV_ROOT_PATH分別對應遠端伺服器上線上、測試node服務存放路徑 - CI_PROJECT_NAME表示gitlab上倉庫名稱 stages: - dev_deploy - master_deploy master_deploy: stage: master_deploy image: ansible映象地址 script: - echo \"${HOST}\" ansible_ssh_user=\"${USER}\" ansible_ssh_pass=\"${PASS}\" ansible_ssh_host=\"${HOST}\" > hosts - echo ansible-playbook ansible.yaml -e hosts=${HOST} -i ./hosts - ansible-playbook ansible.yaml -e "HOST=${HOST} DEST_PATH=${ROOT_PATH}/${CI_PROJECT_NAME} DOCKER_CONTAINER_NAME=${DOCKER_CONTAINER} CUR_BRANCH=${BRANCH}" -i ./hosts - rm -f hosts only: - master tags: - k8s dev_deploy: stage: dev_deploy image: ansible映象地址 script: - echo \"${HOST}\" ansible_ssh_user=\"${USER}\" ansible_ssh_pass=\"${PASS}\" ansible_ssh_host=\"${HOST}\" > hosts - echo ansible-playbook ansible.yaml -e hosts=${HOST} -i ./hosts - ansible-playbook ansible.yaml -e "HOST=${HOST} DEST_PATH=${DEV_ROOT_PATH}/${CI_PROJECT_NAME} DOCKER_CONTAINER_NAME=${DEV_DOCKER_CONTAINER} CUR_BRANCH=${DEV_BRANCH}" -i ./hosts - rm -f hosts only: - dev tags: - k8s
ansible.yml檔案編寫
# cd到node服務server目錄,切換分支,拉取最新程式碼,docker容器重新啟動 - name: deploy hosts: "{{ HOST }}" become_user: root become: yes tasks: # 任務 - name: git checkout branch command: git checkout "{{CUR_BRANCH}}" args: chdir: "{{ DEST_PATH }}" - name: git pull command: git pull args: chdir: "{{ DEST_PATH }}" - name: docker restart container command: docker restart "{{ DOCKER_CONTAINER_NAME }}" args: chdir: "{{ DEST_PATH }}"
遠端伺服器node服務(測試/線上)目錄下執行如下命令
# 測試目錄 /opt/xxx/server-test/server docker-compose up -d # 線上目錄 /opt/xxx/server-prod/server docker-compose -f docker-compose.prod.yml up -d
啟動成功之後通過docker ps -a
檢視容器啟動情況,具體如下圖所示:
說明:
測試環境:本地dev分支程式碼提交或其他分支合併到dev分支時,會通過itlab CI、Ansible自動化部署node服務到遠端伺服器,在對應伺服器遠端目錄下切換分支、拉取最新程式碼、重新啟動對應的測試docker容器
線上環境:本地master分支程式碼提交或其他分支合併到master分支時,會通過itlab CI、Ansible自動化部署node服務到遠端伺服器,在對應伺服器遠端目錄下切換分支、拉取最新程式碼、重新啟動對應的線上docker容器
問題一:測試/線上遠端node服務目錄下沒有node_modules目錄和dist目錄,即沒有下圖這兩個檔案同時遠端伺服器器上檢視docker容器紀錄檔報如下錯誤(這個問題排查了好久才解決)
排查: 發現和正常啟動的node服務容器對比來看,沒有這兩個目錄(dist和node_modules),排查是不是docker-compose.yml中command執行命令有問題,即docker-compose.yml的command中yarn && yarn start是不是有問題,於是嘗試把yarn操作放在package.json中,結果好啦。
解決:
# 修改前 # docker-compose.yml version: '3.0' services: ... server: ... command: yarn && yarn start # package.json "scripts": { ... "build": "nest build", "start": "cross-env NODE_ENV=development nest start", "start:prod": "cross-env NODE_ENV=production yarn build && node dist/src/main", ... }, # 修改後 # docker-compose.yml version: '3.0' services: ... server: ... command: yarn start # package.json 方案一: "scripts": { ... "build": "nest build", "start": "yarn && cross-env NODE_ENV=development nest start", "start:prod": "yarn && yarn build && cross-env NODE_ENV=production node dist/src/main", ... }, 方案二: "scripts": { ... "build": "nest build", "start": "cross-env NODE_ENV=development nest start", "prestart": "yarn", "start:prod": "yarn build && cross-env NODE_ENV=production node dist/src/main", "prestart:prod": "yarn", ... },
注意:
cross-env的位置,放在可執行命令之前,在本專案中,放在最前面伺服器上報cross-env not found, 放在最後面環境變數不生效,NODE_ENV顯示undefined
script中可執行命令注意執行順序,比如yarn && yarn build && cross-env NODE_ENV=production node dist/src/main
script中pre
問題2: 前端線上域名對映不生效,nginx組態檔對映線上域名之後,發現存取線上域名時,發現頁面沒有生效
排查:將nginx測試組態檔和線上組態檔對比,發現檔案內容除了域名和api代理,其餘都是一樣,那到底是什麼原因呢?最後發現竟然是線上nginx組態檔字尾名不對,寫的是xxx.confg,此處心裡一萬個想打死自己
解決: 修改線上nginx組態檔為正確的字尾,即xxx.conf字尾
問題三:Gitlab CI執行異常,具體報錯資訊大概是報/server目錄找不到
排查:在CI裡面列印輸出CI變數以及拼接出來的目錄變數,檢視是哪一步有問題,經排查發現都是正常的,唯一不同的一點是CI變數後面設定了環境變數
解決:嘗試把環境變數改為All default,結果好了,記住,不要隨意設定CI後面的環境變數,如果修改的話,對應的Gitlab裡面也是對應需要對映的,環境變數位置如下圖所示:
master_deploy: ... script: ... - echo ${ROOT_PATH} - echo ${CI_PROJECT_NAME} - echo ${ROOT_PATH}/${CI_PROJECT_NAME} - echo ${DOCKER_CONTAINER} - echo ${BRANCH} ... ...
本文到這就結束了,後面還會有一篇檔案,講全棧專案從開發到自動化部署整個過程(用到的技術棧是Vue + Nest + Typeorm + Mysql+ Gitlab CI + Ansible + Docker)。
推薦學習:《》、《》
以上就是聊聊如何通過docker-compose將node服務部署到多套環境中的詳細內容,更多請關注TW511.COM其它相關文章!