GitLab CI/CD에서 SCP를 통한 배포와 함께 Composer 및 npm 스크립트 실행
GitLab v19.5Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
요약
GitLab CI/CD를 사용해 PHP 프로젝트의 의존성을 빌드하면서 npm 스크립트로 에셋을 컴파일합니다. 사용자 정의 PHP 및 Node.js 버전으로 자체 이미지를 만들 수도 있습니다. 다음 단계는 zip/unzip 패키지와 Node.js를 설치하고 Composer를 사용할 수 있게 만드는 것입니다.
GitLab CI/CD를 사용해 PHP 프로젝트의 의존성을 빌드하면서 npm 스크립트로 에셋을 컴파일합니다.
사용자 정의 PHP 및 Node.js 버전으로 자체 이미지를 만들 수도 있습니다. 간결함을 위해 이 가이드에서는 공식 php Docker 이미지를 사용하고 before_script에서 Node.js를 설치합니다.
image: php:8.3
다음 단계는 zip/unzip 패키지와 Node.js를 설치하고 Composer를 사용할 수 있게 만드는 것입니다. 다음 내용을 before_script 섹션에 넣습니다.
before_script:
- apt-get update
- apt-get install -y git zip unzip nodejs npm
- 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 스크립트입니다.
- CSS 및 JS 컴파일
- 스프라이트 생성
- 다양한 에셋(이미지, 폰트)을 여러 위치로 복사
- 일부 문자열 치환
이 모든 작업은 모든 파일을 build 폴더에 넣으며, 이 폴더는 실제 서버에 배포할 준비가 됩니다.
실제 서버로 파일을 전송하는 방법#
rsync, SCP, SFTP 등 여러 옵션을 사용할 수 있습니다. 여기서는 SCP를 사용합니다.
이를 위해서는 GitLab CI/CD 변수(gitlab.example/your-project-name/variables에서 접근 가능)를 추가해야 합니다. 이 변수의 이름을 STAGING_PRIVATE_KEY로 지정하고 서버의 private 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'
이 스크립트는 다음 작업을 수행합니다.
ssh-agent를 사용할 수 있는지 확인하고, 없으면 설치합니다.~/.ssh폴더를 생성합니다.- 스크립트 실행 환경이 bash로 실행되고 있는지 확인합니다.
- 호스트 확인을 비활성화합니다. 모든 연결은 새로운 환경에서 이루어지므로, 호스트 확인을 비활성화하면 GitLab이 매번 연결 전에 사용자에게 서버의 신원을 확인하고 수락하도록 요청하지 않습니다.
이것이 before_script 섹션에 필요한 내용의 전부입니다.
배포 방법#
Docker 이미지에서 서버로 build 폴더를 배포하려면 새 job을 생성합니다.
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"
세부 내용은 다음과 같습니다.
rules:if: $CI_COMMIT_BRANCH == "dev"는 이 빌드가dev브랜치에 푸시될 때만 실행됨을 의미합니다. 이 블록을 완전히 제거하고 모든 푸시에서 전부 실행되게 할 수도 있습니다(다만 이는 원하지 않는 동작일 가능성이 높습니다).ssh-add ...는 웹 UI에서 추가한 private 키를 Docker 컨테이너에 추가합니다.ssh를 사용해 연결하고 새_tmp폴더를 생성합니다.scp를 사용해 연결하고 (npm스크립트로 생성된)build폴더를 이전에 생성한_tmp폴더로 업로드합니다.- 다시
ssh를 사용해 연결하고live폴더를_old폴더로 이동한 다음,_tmp를live로 이동합니다. - SSH로 연결해
_old폴더를 제거합니다.
artifacts 섹션은 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
문제는 서버에 앱이 존재하지 않는 짧은 시간이 발생한다는 점입니다.
따라서 프로덕션 환경에서는 추가 단계를 통해 언제든지 정상 작동하는 앱이 존재하도록 보장합니다.
다음 단계#
이 예시는 WordPress 프로젝트였기 때문에 실제 코드 스니펫을 포함하고 있습니다. 이어서 시도해 볼 수 있는 아이디어는 다음과 같습니다.
- 기본 브랜치용 스크립트를 약간 다르게 구성하면 해당 브랜치에서는 프로덕션 서버로 배포하고, 다른 브랜치에서는 스테이징 서버로 배포할 수 있습니다.
- 실제 서버로 바로 푸시하는 대신 WordPress 공식 리포지터리로 푸시할 수 있습니다.
- i18n 텍스트 도메인을 즉석에서 생성할 수 있습니다.
최종 .gitlab-ci.yml은 다음과 같습니다.
stage_deploy:
image: php:8.3
artifacts:
paths:
- build/
rules:
- if: $CI_COMMIT_BRANCH == "dev"
before_script:
- apt-get update
- apt-get install -y git zip unzip nodejs npm
- 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"