>  기사  >  운영 및 유지보수  >  docker-compose를 통해 여러 환경에 노드 서비스를 배포하는 방법에 대해 이야기해 보겠습니다.

docker-compose를 통해 여러 환경에 노드 서비스를 배포하는 방법에 대해 이야기해 보겠습니다.

青灯夜游
青灯夜游앞으로
2022-01-28 18:00:433877검색

docker-compose를 통해 node서비스를 여러 환경에 배포하는 방법은 무엇입니까? 다음 글에서는 Docker-compose를 사용하여 여러 환경에 Node 서비스를 배포하는 방법을 소개하겠습니다. 도움이 되길 바랍니다.

docker-compose를 통해 여러 환경에 노드 서비스를 배포하는 방법에 대해 이야기해 보겠습니다.

일반적으로 프로젝트가 개발된 후에는 테스트, 샌드박스, 통합 등 여러 환경에 배포해야 합니다. 그렇다면 docker-compose를 통해 노드 서비스를 여러 환경에 배포하는 방법은 무엇일까요? 아래 글에 자세히 설명되어 있으니 잘못된 부분이 있으면 댓글 달아주세요.

이 기사의 프로젝트에 사용된 기술은 Gitlab+Ansible+Docker노드 서비스 자동 배포(Nest 프레임워크로 작성)입니다. 단계는 다음과 같습니다.

  • docker-compose 및 docker-compose를 작성합니다. prod.yml 구성 파일

  • package.json 수정

  • 원격 서버에 두 개의 디렉토리를 생성하고, 노드 서비스 웨어하우스를 가져오고, 각각 테스트 및 온라인 노드 서비스를 나타내는 다른 분기로 전환

  • .gitlab -ci.yml 파일

  • ansible.yml 파일을 작성하고 원격 서버 노드 서비스(test/online) 디렉터리에 다음 명령어를 실행한다. 실행 후 docker ps -a를 통해 컨테이너가 정상적으로 시작되는지 확인한다. , up 상태에서 멈추면 컨테이너가 성공적으로 시작되었음을 증명합니다. docker 로그 -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 ps -a查看容器是否正常启动,如果是up状态挂起,证明容器启动成功了。docker logs -f 容器id查看容器日志

# 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、docker-compose.prod.yml配置文件

# 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
# 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",
    ...
  },
...
  • package.json中做如下修改

# 测试(dev分支),git clone node服务地址,切换到dev分支
/opt/xxx/server-test/server

# 线上(master分支),git clone node服务地址,切换到master分支
/opt/xxx/server-prod/server
  • 远程服务器上创建两个目录,分别存放测试、线上node服务

# 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
  • .gitlab-ci.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 }}"
  • ansible.yml文件编写

# 测试目录 /opt/xxx/server-test/server
docker-compose up -d

# 线上目录 /opt/xxx/server-prod/server
docker-compose -f docker-compose.prod.yml up -d
  • 远程服务器node服务(测试/线上)目录下执行如下命令

# 修改前
# 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",
    ...
},

启动成功之后通过docker ps -a查看容器启动情况,具体如下图所示:

docker-compose를 통해 여러 환경에 노드 서비스를 배포하는 방법에 대해 이야기해 보겠습니다.

说明

  • 测试环境:本地dev分支代码提交或其他分支合并到dev分支时,会通过itlab CI、Ansible自动化部署node服务到远程服务器,在对应服务器远程目录下切换分支、拉取最新代码、重启对应的测试docker容器

  • 线上环境:本地master分支代码提交或其他分支合并到master分支时,会通过itlab CI、Ansible自动化部署node服务到远程服务器,在对应服务器远程目录下切换分支、拉取最新代码、重启对应的线上docker容器

遇到的问题

问题一:测试/线上远程node服务目录下没有node_modules目录和dist目录,即没有下图这两个文件同时远程服务器器上查看docker容器日志报如下错误(这个问题排查了好久才解决

docker-compose를 통해 여러 환경에 노드 서비스를 배포하는 방법에 대해 이야기해 보겠습니다.

docker-compose를 통해 여러 환경에 노드 서비스를 배포하는 방법에 대해 이야기해 보겠습니다.

排查: 发现和正常启动的node服务容器对比来看,没有这两个目录(dist和node_modules),排查是不是docker-compose.yml中command执行命令有问题,即docker-compose.yml的command中yarn && yarn start是不是有问题,于是尝试把yarn操作放在package.json中,结果好啦。

解决:

master_deploy:
  ...
  script:
    ...
    - echo ${ROOT_PATH}
    - echo ${CI_PROJECT_NAME}
    - echo ${ROOT_PATH}/${CI_PROJECT_NAME}
    - echo ${DOCKER_CONTAINER}
    - echo ${BRANCH}
    ...
 ...

注意

  • cross-env的位置,放在可执行命令之前,在本项目中,放在最前面服务器上报cross-env not found, 放在最后面环境变量不生效,NODE_ENV显示undefined

  • script中可执行命令注意执行顺序,比如yarn && yarn build && cross-env NODE_ENV=production node dist/src/main

    docker-compose, docker-compose.prod.yml 구성 파일 작성
  • rrreeerrreee

package.json에서 다음과 같이 수정합니다

rrreee

원격 서버에 테스트 및 온라인 노드 서비스를 각각 저장할 두 개의 디렉터리를 만듭니다.

rrreee

.gitlab-ci.yml 파일 쓰기🎜🎜 🎜rrreee🎜🎜🎜ansible.yml 파일 쓰기🎜🎜🎜rrreee🎜🎜🎜원격 서버 노드 서비스(테스트/온라인) 디렉터리에서 다음 명령을 실행🎜🎜🎜rrreee🎜성공적으로 시작 후 docker ps -a를 전달합니다. code>아래 그림과 같이 컨테이너 시작 상태를 확인합니다. 🎜🎜<img src="https://img.php.cn/upload/image/795/886/918/1643363755384508.png" title="1643363755384508.png " alt="docker-compose를 통해 여러 환경에 노드 서비스를 배포하는 방법에 대해 이야기해 보겠습니다.">🎜🎜🎜Note🎜:🎜<ul>🎜🎜테스트 환경: 로컬 dev 브랜치 코드가 제출되거나 다른 브랜치가 dev 브랜치에 병합되면 노드 서비스 itlab CI 및 Ansible을 통해 자동으로 배포되며 해당 서버의 원격 디렉터리에서 분기를 전환하고 최신 코드를 가져온 후 해당 테스트 도커 컨테이너를 다시 시작합니다🎜🎜🎜🎜온라인 환경: 로컬 마스터 분기 코드가 제출되거나 다른 브랜치가 마스터 브랜치에 병합되면 itlab CI를 통해 처리됩니다. Ansible은 노드 서비스를 원격 서버에 자동으로 배포하고 해당 서버의 원격 디렉터리에서 브랜치를 전환하고 최신 코드를 가져와 해당 온라인 도커를 다시 시작합니다. Container🎜🎜🎜<h2>발생한 문제</h2>🎜🎜문제 1🎜: test/online 원격 노드 서비스 디렉터리에 node_modules 디렉터리와 dist 디렉터리가 없습니다. 즉, 아래와 같은 두 개의 파일이 없습니다. 동시에 원격 서버에서 도커 컨테이너 로그를 볼 때 다음 오류가 보고됩니다. (🎜이 문제는 해결하는 데 오랜 시간이 걸렸습니다🎜)🎜🎜🎜🎜<img src="https://img.php.cn/upload/image/%20770/228/862/164336376434247docker-compose%EB%A5%BC%20%ED%86%B5%ED%95%B4%20%EC%97%AC%EB%9F%AC%20%ED%99%98%EA%B2%BD%EC%97%90%20%EB%85%B8%EB%93%9C%20%EC%84%9C%EB%B9%84%EC%8A%A4%EB%A5%BC%20%EB%B0%B0%ED%8F%AC%ED%95%98%EB%8A%94%20%EB%B0%A9%EB%B2%95%EC%97%90%20%EB%8C%80%ED%95%B4%20%EC%9D%B4%EC%95%BC%EA%B8%B0%ED%95%B4%20%EB%B3%B4%EA%B2%A0%EC%8A%B5%EB%8B%88%EB%8B%A4." title="164336376434247docker-compose를 통해 여러 환경에 노드 서비스를 배포하는 방법에 대해 이야기해 보겠습니다." alt="docker-compose를 통해 여러 환경에 노드 서비스를 배포하는 방법에 대해 이야기해 보겠습니다.">🎜🎜🎜문제 해결: 🎜 발견 및 정상 시작된 노드 서비스 컨테이너를 비교하면 이 두 디렉터리가 없습니다(dist 및 node_modules) docker-compose.yml의 명령 실행 명령에 문제가 있는지, 즉 docker-compose.yml 명령의 Yarn start가 Yarn && Yarn Start인지 확인하십시오. package.json에 실 연산을 넣어봤는데 결과는 괜찮았습니다. 🎜🎜🎜해결책: 🎜🎜rrreee🎜🎜참고🎜: 🎜🎜🎜🎜cross-env의 위치는 실행 가능한 명령 앞에 배치됩니다. 이 프로젝트에서는 서버에서 cross-env를 찾을 수 없다고 보고합니다. 위의 환경 변수는 적용되지 않으며 NODE_ENV는 undefine🎜🎜🎜🎜<code>yarn && Yarn build && cross-env NODE_ENV=와 같은 스크립트에서 실행 가능한 명령의 실행 순서에 주의하세요. 프로덕션 노드 dist/src/main🎜🎜🎜 🎜pre🎜🎜🎜🎜🎜스크립트 문제 2🎜: nginx 구성 파일이 온라인 도메인 이름을 매핑한 후 프런트 엔드 온라인 도메인 이름 매핑이 적용되지 않습니다. , 온라인 도메인 이름에 접근하면 페이지가 적용되지 않는 것으로 나타났습니다🎜🎜🎜Troubleshooting🎜: Test nginx 구성 파일과 온라인 구성 파일을 비교한 결과, 도메인 이름과 api 프록시를 제외한 내용은 파일의 내용이 동일합니다. 이유는 무엇입니까? 마지막으로 온라인 nginx 구성 파일의 접미사 이름이 잘못되었음을 발견했습니다. xxx.confg로 작성되었습니다. 여기서 자살하고 싶었습니다🎜🎜🎜해결책🎜: 온라인 nginx 구성 파일을 올바른 접미사로 수정하세요. xxx.conf 접미사🎜

问题三:Gitlab CI执行异常,具体报错信息大概是报/server目录找不到

排查:在CI里面打印输出CI变量以及拼接出来的目录变量,查看是哪一步有问题,经排查发现都是正常的,唯一不同的一点是CI变量后面设置了环境变量

解决:尝试把环境变量改为All default,结果好了,记住,不要随意配置CI后面的环境变量,如果修改的话,对应的Gitlab里面也是对应需要映射的,环境变量位置如下图所示:

docker-compose를 통해 여러 환경에 노드 서비스를 배포하는 방법에 대해 이야기해 보겠습니다.

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视频教程》、《nodejs 教程

위 내용은 docker-compose를 통해 여러 환경에 노드 서비스를 배포하는 방법에 대해 이야기해 보겠습니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 juejin.cn에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제