GitLab CI/CD를 통한 SCP로 Composer 및 npm 스크립트 실행

Tier: Free, Premium, Ultimate Offering: GitLab.com, Self-managed, GitLab Dedicated

이 안내서는 GitLab CI/CD를 사용하여 PHP 프로젝트의 종속성을 빌드하고 npm 스크립트를 통해 에셋을 컴파일하는 과정을 다룹니다.

사용자 정의 PHP 및 Node.js 버전이 포함된 이미지를 만들 수 있지만, 간결함을 위해 PHP와 Node.js가 모두 설치된 기존 Docker 이미지를 사용합니다.

image: tetraweb/php

다음 단계는 zip/unzip 패키지를 설치하고 composer를 사용할 수 있도록 하는 것입니다. 이들은 before_script 섹션에 추가됩니다.

before_script:
  - apt-get update
  - apt-get install zip unzip
  - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
  - php composer-setup.php
  - php -r "unlink('composer-setup.php');"

이렇게 함으로써 모든 요구 사항을 갖추게 됩니다. 다음으로 composer install을 실행하여 모든 PHP 종속성을 가져오고 npm install을 실행하여 Node.js 패키지를 로드합니다. 그런 다음 npm 스크립트를 실행합니다. 이들을 before_script 섹션에 추가해야 합니다.

before_script:
  # ...
  - php composer.phar install
  - npm install
  - npm run deploy

특별한 경우에는 npm deploy 스크립트가 다음을 수행하는 Gulp 스크립트입니다:

  1. CSS 및 JS 컴파일
  2. 스프라이트 생성
  3. 여러 에셋(이미지, 폰트)을 복사
  4. 일부 문자열 교체

모든 이러한 작업은 모든 파일을 build 폴더에 넣어줍니다. 이 폴더는 실제 서버에 배포할 준비가 끝난 상태입니다.

실제 서버로 파일 전송하는 방법

rsync, SCP, 또는 SFTP와 같은 여러 옵션이 있습니다. 현재는 SCP를 사용합니다.

이를 수행하려면 GitLab CI/CD 변수를 추가해야 합니다 (gitlab.example/your-project-name/variables에서 액세스 가능). 이 변수의 이름을 STAGING_PRIVATE_KEY로 지정하고 서버의 개인 SSH 키로 설정해야 합니다.

보안 팁

업데이트가 필요한 폴더에만 액세스 권한을 갖는 사용자를 만드십시오.

이 변수를 만든 후, 해당 키가 Docker 컨테이너에서 실행될 때 추가되었는지 확인해야 합니다.

before_script:
  # - ....
  - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
  - mkdir -p ~/.ssh
  - eval $(ssh-agent -s)
  - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'

순서대로 진행되는 것은 다음과 같습니다:

  1. ssh-agent를 사용할 수 있는지 확인하고 사용할 수 없는 경우 설치합니다.
  2. ~/.ssh 폴더를 만듭니다.
  3. bash를 실행하는지 확인합니다.
  4. 호스트 확인을 비활성화합니다 (첫 번째 서버 연결 시 사용자 수락을 요청하지 않고, 각 작업이 첫 번째 연결과 동일하기 때문에 필요합니다).

이것이 모두 before_script 섹션에서 필요한 내용입니다.

배포하는 방법

위에서 언급한대로, Docker 이미지의 build 폴더를 서버로 배포해야 합니다. 이를 수행하려면 새 작업을 만들어야 합니다:

stage_deploy:
  artifacts:
    paths:
      - build/
  rules:
    - if: $CI_COMMIT_BRANCH == "dev"
  script:
    - ssh-add <(echo "$STAGING_PRIVATE_KEY")
    - ssh -p22 server_user@server_host "mkdir htdocs/wp-content/themes/_tmp"
    - scp -P22 -r build/* server_user@server_host:htdocs/wp-content/themes/_tmp
    - ssh -p22 server_user@server_host "mv htdocs/wp-content/themes/live htdocs/wp-content/themes/_old && mv htdocs/wp-content/themes/_tmp htdocs/wp-content/themes/live"
    - ssh -p22 server_user@server_host "rm -rf htdocs/wp-content/themes/_old"

아래는 각 단계입니다:

  1. rules:if: $CI_COMMIT_BRANCH == "dev"은 이 작업이 dev 브랜치에 푸시될 때에만 실행됨을 의미합니다. 이 블록을 완전히 제거하고 모든 푸시에서 실행하도록 할 수 있지만, 아마 원하지 않는 결과일 것입니다.
  2. ssh-add... 웹 UI에서 추가한 해당 프라이빗 키를 Docker 컨테이너에 추가합니다.
  3. ssh를 통해 연결하고 새 _tmp 폴더를 만듭니다.
  4. scp를 통해 npm 스크립트로 생성된 build 폴더를 이전에 만든 _tmp 폴더로 업로드합니다.
  5. 다시 ssh를 통해 live 폴더를 _old 폴더로 이동한 다음, _tmplive로 이동합니다.
  6. SSH를 통해 _old 폴더를 제거합니다.

아티팩트는 무엇일까요? GitLab CI/CD에게 build 디렉토리를 유지하도록 지시합니다 (나중에 필요할 때 다운로드할 수 있음).

왜 이런 방식으로 하는가

스테이지 서버에만 사용한다면 두 단계로 진행할 수 있습니다:

- ssh -p22 server_user@server_host "rm -rf htdocs/wp-content/themes/live/*"
- scp -P22 -r build/* server_user@server_host:htdocs/wp-content/themes/live

그러나 서버에 애플리케이션이 없는 짧은 시간이 발생합니다.

따라서 프로덕션 환경에서는 시간이 지날 때마다 작동하는 앱이 있도록 추가 단계를 사용합니다.

다음 단계

워드프레스 프로젝트였기 때문에 실제 코드 스니펫이 포함되어 있습니다. 추후 사용 가능한 몇 가지 아이디어는 다음과 같습니다:

  • 기본 브랜치에 대해 약간 다른 스크립트를 갖는 것은 본 브랜치에서는 프로덕션 서버로, 다른 브랜치에서는 스테이지 서버로 배포할 수 있도록 합니다.
  • 실시간으로 i18n 텍스트 도메인을 생성할 수 있습니다.

최종 .gitlab-ci.yml은 다음과 같습니다:

stage_deploy:
  image: tetraweb/php
  artifacts:
    paths:
      - build/
  rules:
    - if: $CI_COMMIT_BRANCH == "dev"
  before_script:
    - apt-get update
    - apt-get install zip unzip
    - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
    - php composer-setup.php
    - php -r "unlink('composer-setup.php');"
    - php composer.phar install
    - npm install
    - npm run deploy
    - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
    - mkdir -p ~/.ssh
    - eval $(ssh-agent -s)
    - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
  script:
    - ssh-add <(echo "$STAGING_PRIVATE_KEY")
    - ssh -p22 server_user@server_host "mkdir htdocs/wp-content/themes/_tmp"
    - scp -P22 -r build/* server_user@server_host:htdocs/wp-content/themes/_tmp
    - ssh -p22 server_user@server_host "mv htdocs/wp-content/themes/live htdocs/wp-content/themes/_old && mv htdocs/wp-content/themes/_tmp htdocs/wp-content/themes/live"
    - ssh -p22 server_user@server_host "rm -rf htdocs/wp-content/themes/_old"