NGINX Unit을 사용하여 애플리케이션 스택 구축
개발자들은 애플리케이션 스택에서 NGINX Unit 을 사용하는 방법을 자주 묻습니다. 자체적으로 NGINX Unit은 구성하기가 매우 쉽지만, 이를 다양한 도구 및 서비스 세트에 주입하는 적절한 방법은 어려울 수 있습니다. 고객의 잠재적인 이점에도 동일한 질문이 적용됩니다. 이 포스트는 일반적인 사용 사례와 이 주제에 대해 설명하는 것을 목표로 합니다.
목차
1. 문제: 복잡한 애플리케이션 배포 Workflow
2. 솔루션: Docker 및 NGINX Unit
3. NGINX Unit 개발 환경 설정
4. 환경 변수 사용
5. 결론
1. 문제: 복잡한 애플리케이션 배포 Workflow
많은 독자들이 직면한 문제는 특정 비즈니스 요구사항에 맞는 특정 라이브러리, 모듈 및 확장뿐만 아니라 사용자 지정 언어 런타임 버전을 포함하는 Production 환경 배포 절차를 자동화해야 한다는 것입니다. 일반적으로 이 작업은 적절한 임시 작업으로 수행할 수 있지만 사용자 지정 반수 동 Workflow를 더 큰 대규모에 적합한 자동화 단계로 전환하는 것은 너무 난이도가 높고 기간이 오래 걸려 프로젝트를 완전히 폐기할 수도 있습니다. 이 경우 NGINX Unit이 어떻게 문제를 단순화하는지 알아보겠습니다.
이러한 종류의 시나리오는 일반적으로 다음과 같은 중복 요구사항에 의해 복잡합니다.
- 웹 애플리케이션 자체의 설정 절차 자동화
- 애플리케이션의 요구에 맞게 사용자 정의된 언어 런타임 구축
- 결과 일반 이미지에 배포 관련 설정 주입
- 인스턴스화된 이미지 배포 및 관리
이러한 각 요구 사항은 자체적으로 충족될 수 있지만, 웹 애플리케이션의 흥미로운 부분에 도달하기 위해 모든 단계를 계속해서 반복해야 한다는 부담감이 만만치 않을 수 있습니다. 여기서는 이러한 문제를 완화하고 Pipeline을 설치하는 대신 비즈니스 가치를 추가하는 데 더 많은 시간을 할애할 수 있는 접근 방식을 제안합니다. 그대로 사용하거나 보다 정교한 시나리오에 맞게 조정할 수 있습니다.
2. 솔루션: Docker 및 NGINX Unit
기본적으로, 여기서 설명하는 것은 당신이 선택한 웹 애플리케이션을 위한 NGINX Unit 기반의 Rig이며, 우리의 Timo Stark가 고안하고 GitHub에서 사용할 수 있습니다. Build 스택에는 대상 애플리케이션에 대한 WordPress가 있으며 unitwp이라 합니다. 그러나 다른 옵션에도 적용할 수 있습니다. 예를 들어, 이미 CakePHP 기반 웹사이트인 https://kaufdaheim.org은 독일에서 진행 중인 COVID ‑ 19 봉쇄 기간 동안 지역 기업들이 생존할 수 있도록 돕고 있습니다.
여기에 설명된 설정은 PHP 지원이 내장된 사용자 지정 NGINX Unit 기반 컨테이너 이미지를 거의 쉽게 생성하고, 이미지 내부에 WordPress 설치를 준비하며 NGINX Unit에서 시작하도록 웹 애플리케이션을 준비하고, 사전에 구성된 포트에서 실행 및 노출합니다. 개발 환경 설정 및 환경 변수 사용에서 설명된 이유로 인해 설정은 의도적으로 데이터베이스 포함을 피합니다.
이 솔루션은 PHP 7.3 런타임과 NGINX Unit에 적합한 언어 모듈로 사전 구성된 공식 NGINX Unit 이미지를 사용하므로 사용자 지정 이미지를 준비하는 것보다 훨씬 많은 시간과 노력을 절약할 수 있습니다. 필요에 따라 Build 할 수 있는 기본 Docker 이미지를 선호하는 경우 핵심 NGINX Unit 실행 파일만 포함하는 nginx/unit:1.16.0-minimal 이미지를 사용하십시오.
Note: 다음 단계에서는 PHP용 Composer 종속성 관리자가 있다고 가정합니다. 필요한 경우 다운로드 지침을 따르십시오. 그렇지 않으면 사용 가능한 다른 설치 방법을 계속 사용할 수 있습니다.
GitHub에서 Composer ‑ Enabled WordPress Fork를 사용하는 다음과 같은 기본 Composer 구성을 사용하여 WordPress 애플리케이션용 파일의 로컬 복사본을 만드는 것으로 시작합니다.
{
"require": {
"johnpbloch/wordpress": "*"
}
}
자산을 다운로드하고 준비하려면 이 Snippet을 composer.json으로 저장하고 동일한 디렉토리에서 composer install 명령을 실행합니다.
이제 다음 Dockerfile을 사용하여 파일을 Docker 이미지에 Load해 보겠습니다.
FROM nginx/unit:1.16.0-php7.3
RUN mkdir /var/apphome/ && groupadd -r wpgroup && useradd --no-log-init -r -g wpgroup wpuser && \
chown -R wpuser:wpgroup /var/apphome/ && \
apt-get update && apt-get install --no-install-recommends --no-install-suggests -y php7.3-mysql php7.3-gd
COPY wordpress /var/apphome
RUN chown -R wordpress:wordpress /var/apphome/
COPY .unit.conf.json /docker-entrypoint.d/.unit.conf.json
CMD ["unitd", "--no-daemon", "--control", "unix:/var/run/control.unit.sock"]
이 파일은 먼저 WordPress에 필요한 몇 가지 패키지로 기본 이미지의 PHP 환경을 사용자 정의합니다. 프로젝트에 추가 패키지 또는 사용자 지정이 필요한 경우 이 확장 지점이 첫 번째 확장 지점입니다. 전체 도구 모음을 직접 Build 하려는 경우 위에서 언급한 대로 -minimal 기본 이미지로 시작할 수 있습니다.
그런 다음 파일은 Composer에서 생성한 디렉토리의 이미지로 WordPress 파일을 복사하고 적절한 소유권을 설정합니다. 마지막으로 컨테이너가 시작될 때 NGINX Unit 구성에 업로드될 JSON Snippet에 복사합니다. startup 스크립트는 자동으로 작동하지만 Custom Certificate 및 Shell 스크립트를 사용할 수도 있습니다.
다음은 NGINX Unit 구성입니다.
{
"listeners": {
"*:8080": {
"pass": "routes/wordpress"
}
},
"routes": {
"wordpress": [
{
"match": {
"uri": [
"*.php",
"*.php/*",
"/wp-admin/"
]
},
"action": {
"pass": "applications/wp_direct"
}
},
{
"action": {
"share": "/var/apphome",
"fallback": {
"pass": "applications/wp_index"
}
}
}
]
},
"applications": {
"wp_direct": {
"type": "php",
"options": {
"file": "/etc/php.ini",
"admin": {
"upload_max_filesize": "20M"
}
},
"user": "wordpress",
"group": "wordpress",
"root": "/var/apphome"
},
"wp_index": {
"type": "php",
"options": {
"file": "/etc/php.ini",
"admin": {
"upload_max_filesize": "20M"
}
},
"user": "wpuser",
"group": "wpgroup",
"root": "/var/apphome",
"script": "index.php"
}
},
"settings": {
"http": {
"header_read_timeout": 10,
"body_read_timeout": 10,
"send_timeout": 10,
"idle_timeout": 120,
"max_body_size": 6291456,
"static": {
"mime_types": {
"text/plain": [
".log",
"README",
"CHANGES"
]
}
}
}
}
}
WordPress 관련 라우팅 체계(WordPress how-to에서 채택된)는 NGINX의 try_files 지시어와 유사한 NGINX Unit 1.16.0에 도입된 fallback 라우팅 옵션을 사용합니다. 애플리케이션 섹션에 있는 별도의 wp_direct 및 wp_index 개체에서 웹 사이트의 다른 부분에 다른 설정을 적용했음에도 유의하십시오. 원하는 경우 다른 php.ini 파일을 사용할 수도 있습니다.
마지막으로, 이 모든 것은 build.sh 스크립트로 마무리합니다.
#!/usr/bin/env bash
set -ex
build_container() {
docker build -t YOURIMAGETAG --no-cache .
}
containerize() {
echo "Building Container Image"
build_container
docker tag YOURIMAGETAG:latest REMOTEIMAGETAG:latest
echo "Pushing... "
docker push REMOTEIMAGETAG:latest
}
case $1 in
"push")
echo "Building and Pushing to Registry ..."
containerize
;;
esac
YOURIMAGETAG는 로컬 태그로 대체하고, REMOTEIMAGETAG는 대상 Docker 레지스트리의 이름을 포함된 최종 태그로 대체합니다. 간결함을 위해 스크립트는 오류 처리 및 보고를 생략합니다.
build.sh Push 명령을 실행하면 스크립트가 처음부터 새 이미지를 Build하고 태그를 지정한 다음 선택한 레지스트리에 Push합니다. 예를 들어 조정 가능한 태그 및 버전 관리를 도입하거나 복잡함을 줄이기 위해 동일한 이미지의 오래된 버전을 스크랩하는 등 Shell 스크립트도 향상시킬 수 있습니다.
3. NGINX Unit 개발 환경 설정
NGINX Unit의 기능을 훨씬 더 활용할 수 있는 관련 시나리오는 로컬 개발 또는 테스트 환경을 빠르고 쉽게 가동하고 종료해야 한다는 것입니다. NGINX Unit의 동적 구성 기능은 언어 런타임 버전, 환경 변수 또는 작업 중인 애플리케이션의 다른 설정 간에 원활하게 전환할 수 있는 유망한 옵션입니다. 지금까지 달성한 것을 기반으로 합시다.
unitw WordPress 애플리케이션의 개발 버전은 GitHub Repository의 dev 하위 디렉터리에서 찾을 수 있습니다. The Solution: Docker 및 NGINX Unit에서와 기본적으로 동일한 설정을 사용하지만 몇 가지 차이점이 있습니다.
첫 번째 차이점은 Docker 파일에 있습니다. Docker 파일은 WordPress 파일을 이미지에 복사하는 명령 대신 다음과 같은 명령을 사용합니다. 이렇게 변경하면 이미지를 Build할 때마다 특정 php.ini 설정을 추가할 수 있습니다.
COPY php.ini /etc/php/7.3/cli/conf.d/php-unit.ini
또 다른 중요한 차이점은 docker-compose를 사용하여 MariaDB 데이터베이스 컨테이너를 추가하는 것입니다. 다음은 docker-compose.yaml 파일입니다.
version: "3.7"
services:
mariadb:
image: mariadb:latest
ports:
- 3306:3306
restart: always
volumes:
- ./db-volume:/var/lib/mysql
environment:
MYSQL_USER: wordpressdev
MYSQL_PASSWORD: wordpressdev
MYSQL_DATABASE: wordpress
MYSQL_ROOT_PASSWORD: devpassword
wordpress:
image: YOURIMAGETAG:latest
environment:
DB_USER: wordpressdev
volumes:
- ../wordpress:/var/apphome/wordpress
- ../vendor:/var/apphome/vendor
ports:
- 8044:8080
컨테이너당 하나의 서비스를 유지 관리하는 것이 Docker 모범 사례이며, 이것이 우리가 The Solution: Docker 및 NGINX Unit에 데이터베이스를 추가하지 않은 이유입니다. Production 환경에서 데이터베이스 연결은 다양한 형태로 제공될 수 있으므로 특정 데이터베이스를 선택하는 대신 컨테이너를 일반화하고 모든 시나리오에 대비했습니다. 반대로 개발 환경은 일반적으로 독립적이어야 하므로, 이 섹션의 동적 구성은 런타임에 완전히 작동하는 스택을 생성합니다. 이에 대해서는 다음 섹션에서 자세히 설명합니다.
이 설정을 실행하려면 이미지를 Build하고 컨테이너를 실행하기 위한 옵션과 서비스를 중지하고 정리를 수행하기 위한 옵션이 있는 업그레이드된 Shell 스크립트(run-local.sh)가 필요합니다.
#!/usr/bin/env bash
set -ex
case $1 in
"dev")
echo "Building local image and mounting code base..."
docker build -t YOURIMAGETAG:latest .
docker-compose up
;;
"stop")
echo "Stopping services..."
docker-compose down
docker rm --force dev_wordpress_1
;;
esac
로컬 개발 환경을 시작하고 중지하려면 각각 ./run-local.sh dev 및 ./run-local.sh stop 명령을 실행합니다.
4. 환경 변수 사용
개발 환경에서는 일회용 자격 증명을 잘 보이는 곳에 저장하는 것이 합리적이지만, 하드코딩된 데이터베이스 암호 또는 API Access Token을 Production Repository에 Push하는 것은 결코 좋은 생각이 아닙니다. 이러한 문제를 방지하는 방법은 여러 가지가 있지만 하드코딩된 자격 증명에 대한 가장 기본적인 대안 중 하나는 환경 변수입니다.
다음을 포함하여 다양한 방법으로 환경 변수를 설정할 수 있습니다.
- 시작할 때 docker run –env 또는 docker run –env-file 명령에 대한 인수로 제공
- 개발 환경 설정에서와 같이 docker-compose.yaml 파일에 나열합니다.
- 마지막으로 NGINX Unit 구성 API의 애플리케이션 개체, 특히 해당 환경 옵션을 사용합니다.
NGINX Unit 구성의 개발 버전에서는 다음 예제와 같이 두 애플리케이션에 대한 환경 옵션을 사용합니다.
"applications": {
"wp_direct": {
"type": "php",
"environment": {
"DB_HOST": "mariadb"
},
}
},
보시다시피 환경 섹션의 JSON은 다소 간단합니다. 애플리케이션에 대한 변수 이름 및 해당 설정의 Key – Value 목록을 제공합니다. 여기서 장점은 값이 단일 애플리케이션에만 표시된다는 것입니다. 동일한 환경의 다른 애플리케이션과 공유되지 않습니다.
물론 구체적인 방법의 선택은 귀하에게 달려 있습니다. 그러나 단일 지점을 선택하여 환경 변수를 구성하고 해당 선택 사항을 고수하는 것이 좋습니다.
5. 결론
이 포스트 전체에서 설명한 것처럼 NGINX Unit에는 다양한 도구와 기술이 포함된 여러 계층의 시나리오를 몇 가지 Shell 명령으로 요약하는 데 도움이 되는 기능과 옵션이 포함되어 있습니다.
- 구성은 동적이므로 애플리케이션 또는 특정 섹션을 즉시 업데이트할 수 있습니다.
- 구성도 세분화되어 있으므로 전체 설정에 영향을 주지 않고 개별 설정을 미세 조정할 수 있습니다.
- Docker 이미지는 조정이 거의 또는 전혀 필요하지 않은 기성 솔루션을 제공하므로 독립형 실행을 위해 모든 애플리케이션을 빠르게 캡슐화하거나 다른 서비스와 함께 배포할 수 있습니다.
이 모든 것이 NGINX Unit을 모든 복잡성과 Volume의 애플리케이션 Delivery 스택에 대한 유력한 후보로 만듭니다. 우리는 요청 라우팅 및 애플리케이션 격리를 개선하기 위해 몇 가지 중요한 업데이트를 진행하고 있으며, 이에 따라 훨씬 더 많은 옵션을 테이블에 가져올 수 있습니다.
NGINX Unit의 최신 소식을 빠르게 전달받고 싶으시면 아래 뉴스레터를 구독하세요.