웹사이트 검색

Docker Compose로 WordPress를 설치하는 방법


소개

PHP 처리. 확장 가능한 플러그인 아키텍처와 템플릿 시스템 덕분에 대부분의 관리는 웹 인터페이스를 통해 수행할 수 있습니다. 이것이 블로그에서 제품 페이지, 전자 상거래 사이트에 이르기까지 다양한 유형의 웹 사이트를 만들 때 WordPress가 널리 사용되는 이유입니다.

WordPress를 실행하려면 일반적으로 Docker Compose를 설치해야 합니다. 원하는 스택을 설정하고 WordPress를 설치하는 프로세스를 간소화할 수 있습니다. 개별 구성 요소를 직접 설치하는 대신 라이브러리, 구성 파일 및 환경 변수와 같은 항목을 표준화하는 이미지를 사용할 수 있습니다. 그런 다음 공유 운영 체제에서 실행되는 격리된 프로세스인 컨테이너에서 이러한 이미지를 실행합니다. 또한 Compose를 사용하면 여러 컨테이너(예: 애플리케이션 및 데이터베이스)를 조정하여 서로 통신할 수 있습니다.

이 자습서에서는 다중 컨테이너 WordPress 설치를 빌드합니다. 컨테이너에는 MySQL 데이터베이스, Nginx 웹 서버 및 WordPress 자체가 포함됩니다. 또한 cron 작업으로 TLS/SSL 인증서를 획득하여 인증서를 갱신하여 도메인을 안전하게 유지함으로써 설치를 보호할 수 있습니다.

전제 조건

이 자습서를 따르려면 다음이 필요합니다.

  • Ubuntu 20.04를 실행하는 서버와 sudo 권한 및 활성 방화벽이 있는 루트가 아닌 사용자. 이를 설정하는 방법에 대한 지침은 초기 서버 설정 가이드를 참조하십시오.\n
  • Ubuntu 20.04에서 Docker를 설치하고 사용하는 방법의 1단계와 2단계에 따라 서버에 Docker를 설치했습니다.\n
  • Ubuntu 20.04에 Docker Compose를 설치하는 방법의 1단계에 따라 서버에 Docker Compose가 설치되었습니다.\n
  • 등록된 도메인 이름입니다. 이 자습서에서는 전체적으로 your_domain을 사용합니다. Freenom에서 무료로 받거나 선택한 도메인 등록 기관을 사용할 수 있습니다.\n
  • 다음 DNS 레코드는 모두 서버에 대해 설정됩니다. DigitalOcean DNS에 대한 이 소개를 따라 DigitalOcean 계정에 추가하는 방법에 대한 자세한 내용을 확인할 수 있습니다.\n
    • 서버의 공용 IP 주소를 가리키는 your_domain이 있는 A 레코드
    • 서버의 공개 IP 주소를 가리키는 www.your_domain이 있는 A 레코드

    모든 것이 설정되면 첫 번째 단계를 시작할 준비가 된 것입니다.

    1단계 - 웹 서버 구성 정의

    컨테이너를 실행하기 전에 첫 번째 단계는 Nginx 웹 서버에 대한 구성을 정의하는 것입니다. 구성 파일에는 자동화된 인증서 갱신을 위해 Let’s Encrypt 확인 요청을 Certbot 클라이언트로 보내는 위치 블록과 함께 일부 WordPress 관련 위치 블록이 포함됩니다.

    먼저 WordPress 설정을 위한 프로젝트 디렉토리를 만듭니다. 이 예에서는 wordpress라고 합니다. 원하는 경우 이 디렉토리의 이름을 다르게 지정할 수 있습니다.

    1. mkdir wordpress

    그런 다음 디렉터리로 이동합니다.

    1. cd wordpress

    다음으로 구성 파일의 디렉터리를 만듭니다.

    1. mkdir nginx-conf

    nano 또는 선호하는 편집기로 파일을 엽니다.

    1. nano nginx-conf/nginx.conf

    이 파일에서 서버 이름 및 문서 루트에 대한 지시문이 있는 서버 블록과 인증서, PHP 처리 및 정적 자산 요청에 대한 Certbot 클라이언트의 요청을 지시하는 위치 블록을 추가합니다.

    파일에 다음 코드를 추가합니다. your_domain을 자신의 도메인 이름으로 바꿔야 합니다.

    server {
            listen 80;
            listen [::]:80;
    
            server_name your_domain www.your_domain;
    
            index index.php index.html index.htm;
    
            root /var/www/html;
    
            location ~ /.well-known/acme-challenge {
                    allow all;
                    root /var/www/html;
            }
    
            location / {
                    try_files $uri $uri/ /index.php$is_args$args;
            }
    
            location ~ \.php$ {
                    try_files $uri =404;
                    fastcgi_split_path_info ^(.+\.php)(/.+)$;
                    fastcgi_pass wordpress:9000;
                    fastcgi_index index.php;
                    include fastcgi_params;
                    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                    fastcgi_param PATH_INFO $fastcgi_path_info;
            }
    
            location ~ /\.ht {
                    deny all;
            }
            
            location = /favicon.ico { 
                    log_not_found off; access_log off; 
            }
            location = /robots.txt { 
                    log_not_found off; access_log off; allow all; 
            }
            location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ {
                    expires max;
                    log_not_found off;
            }
    }
    

    당사 서버 블록에는 다음 정보가 포함됩니다.

    지침:

    • listen: 이것은 Nginx가 포트 80에서 수신하도록 지시하여 인증서 요청에 Certbot의 웹루트 플러그인을 사용할 수 있게 합니다. 아직 포트 443을 포함하지 않았다는 점에 유의하십시오. 인증서를 성공적으로 얻은 후에는 SSL을 포함하도록 구성을 업데이트해야 합니다.
    • server_name: 서버에 대한 요청에 사용해야 하는 서버 이름과 서버 블록을 정의합니다. 이 줄의 your_domain을 자신의 도메인 이름으로 바꿔야 합니다.
    • index: 이 지시문은 서버에 대한 요청을 처리할 때 색인으로 사용될 파일을 정의합니다. 여기에서 기본 우선 순위를 수정하여 index.phpindex.html 앞으로 이동하여 Nginx가 index.php라는 파일의 우선 순위를 지정하도록 했습니다. 가능합니다.
    • root: 이 지시문은 서버에 대한 요청의 루트 디렉토리 이름을 지정합니다. 이 디렉토리 /var/www/htmlWordPress Dockerfile입니다. 이러한 Dockerfile 지침은 또한 WordPress 릴리스의 파일이 이 볼륨에 마운트되도록 합니다.

    위치 블록:

    • location ~ /.well-known/acme-challenge: 이 위치 블록은 Certbot이 임시 파일을 배치할 .well-known 디렉토리에 대한 요청을 처리합니다. 도메인의 DNS가 서버로 확인되는지 확인합니다. 이 구성을 사용하면 Certbot의 웹루트 플러그인을 사용하여 도메인에 대한 인증서를 얻을 수 있습니다.
    • location /: 이 위치 블록에서 try_files 지시문은 개별 URI 요청과 일치하는 파일을 확인하는 데 사용됩니다. 그러나 404 찾을 수 없음 상태를 기본값으로 반환하는 대신 요청 인수를 사용하여 제어권을 WordPress의 index.php 파일로 넘길 것입니다.
    • location ~ \\.php$: 이 위치 블록은 PHP 처리를 처리하고 이러한 요청을 wordpress 컨테이너에 프록시합니다. WordPress Docker 이미지는 이 블록의 FastCGI 프로토콜을 기반으로 하기 때문입니다. Nginx는 PHP 요청을 위해 독립적인 PHP 프로세서가 필요합니다. 이 경우 이러한 요청은 php:fpm 이미지에 포함된 php-fpm 프로세서에 의해 처리됩니다.\n또한 이 위치 블록에는 wordpress 컨테이너에서 실행 중인 WordPress 애플리케이션에 대한 요청을 프록시하고, 구문 분석된 요청 URI에 대한 기본 인덱스를 설정하고, URI 요청을 구문 분석하는 FastCGI 관련 지시문, 변수 및 옵션이 포함되어 있습니다. .
    • location ~ /\\.ht: 이 블록은 Nginx가 파일을 제공하지 않기 때문에 .htaccess 파일을 처리합니다. deny_all 지시문은 .htaccess 파일이 사용자에게 제공되지 않도록 합니다.
    • location=/favicon.ico, location=/robots.txt: 이 블록은 /favicon.ico/robots.txt는 기록되지 않습니다.
    • location ~* \\.(css|gif|ico|jpeg|jpg|js|png)$: 이 블록은 정적 자산 요청에 대한 로깅을 해제하고 이러한 자산이 캐시 가능한지 확인합니다. 일반적으로 게재 비용이 많이 들기 때문입니다.

    FastCGI 프록시에 대한 자세한 내용은 Nginx 서버 및 위치 블록 선택 알고리즘 이해를 참조하세요.

    편집을 마치면 파일을 저장하고 닫습니다. nano를 사용한 경우 CTRL+X, Y, ENTER를 차례로 눌러 수행합니다.

    Nginx 구성이 준비되면 런타임에 애플리케이션 및 데이터베이스 컨테이너에 전달할 환경 변수 생성으로 이동할 수 있습니다.

    2단계 - 환경 변수 정의

    데이터베이스 및 WordPress 애플리케이션 컨테이너는 애플리케이션 데이터를 유지하고 애플리케이션에 액세스할 수 있도록 런타임 시 특정 환경 변수에 액세스해야 합니다. 이러한 변수에는 민감한 정보와 민감하지 않은 정보가 모두 포함됩니다. 즉, MySQL 루트 비밀번호와 애플리케이션 데이터베이스 사용자 및 비밀번호에 대한 민감한 값과 애플리케이션 데이터베이스 이름 및 호스트에 대한 민감하지 않은 정보가 있습니다.

    Docker Compose 파일(컨테이너 실행 방법에 대한 정보가 포함된 기본 파일)에서 이러한 모든 값을 설정하는 대신 .env 파일에서 중요한 값을 설정하고 순환을 제한합니다. 이렇게 하면 이러한 값이 프로젝트 리포지토리로 복사되어 공개적으로 노출되는 것을 방지할 수 있습니다.

    기본 프로젝트 디렉토리인 ~/wordpress에서 .env라는 파일을 엽니다.

    1. nano .env

    이 파일에서 설정하는 기밀 값에는 MySQL 루트 사용자의 암호와 WordPress가 데이터베이스에 액세스하는 데 사용할 사용자 이름 및 암호가 포함됩니다.

    다음 변수 이름과 값을 파일에 추가합니다. 여기에 각 변수에 대해 고유한 값을 제공해야 합니다.

    MYSQL_ROOT_PASSWORD=your_root_password
    MYSQL_USER=your_wordpress_database_user
    MYSQL_PASSWORD=your_wordpress_database_password
    

    루트 관리 계정의 비밀번호와 애플리케이션 데이터베이스의 기본 사용자 이름 및 비밀번호가 포함되어 있습니다.

    편집을 마치면 파일을 저장하고 닫습니다.

    .env 파일에 민감한 정보가 포함되어 있으므로 프로젝트의 .gitignore.dockerignore 파일에 포함되었는지 확인하려고 합니다. 이것은 Git 리포지토리와 Docker 이미지에 각각 복사하지 않을 파일을 Git과 Docker에 알려줍니다.

    버전 제어를 위해 Git을 사용하려는 경우 git init를 사용하여 현재 작업 디렉토리를 리포지토리로 초기화합니다.

    1. git init

    그런 다음 .gitignore 파일을 만들고 엽니다.

    1. nano .gitignore

    파일에 .env를 추가합니다.

    .env
    

    편집을 마치면 파일을 저장하고 닫습니다.

    마찬가지로 .env.dockerignore 파일에 추가하여 이 디렉토리를 빌드로 사용할 때 컨테이너에 저장되지 않도록 하는 것이 좋습니다. 문맥.

    파일 열기:

    1. nano .dockerignore

    파일에 .env를 추가합니다.

    .env
    

    그 아래에서 애플리케이션 개발과 관련된 파일 및 디렉토리를 선택적으로 추가할 수 있습니다.

    .env
    .git
    docker-compose.yml
    .dockerignore
    

    완료되면 파일을 저장하고 닫습니다.

    중요한 정보가 있으면 이제 docker-compose.yml 파일에서 서비스 정의로 이동할 수 있습니다.

    3단계 — Docker Compose로 서비스 정의

    docker-compose.yml 파일에는 설정에 대한 서비스 정의가 포함됩니다. Compose의 서비스는 실행 중인 컨테이너이며 서비스 정의는 각 컨테이너가 실행되는 방법에 대한 정보를 지정합니다.

    Compose를 사용하면 여러 서비스를 정의하여 다중 컨테이너 애플리케이션을 실행할 수 있습니다. Compose를 사용하면 이러한 서비스를 공유 네트워크 및 볼륨과 함께 연결할 수 있기 때문입니다. 데이터베이스, WordPress 애플리케이션 및 웹 서버에 대해 서로 다른 컨테이너를 생성하므로 현재 설정에 도움이 됩니다. 또한 웹 서버에 대한 인증서를 얻기 위해 Certbot 클라이언트를 실행하는 컨테이너를 생성합니다.

    시작하려면 docker-compose.yml 파일을 만들고 엽니다.

    1. nano docker-compose.yml

    다음 코드를 추가하여 Compose 파일 버전 및 db 데이터베이스 서비스를 정의합니다.

    version: '3'
    
    services:
      db:
        image: mysql:8.0
        container_name: db
        restart: unless-stopped
        env_file: .env
        environment:
          - MYSQL_DATABASE=wordpress
        volumes: 
          - dbdata:/var/lib/mysql
        command: '--default-authentication-plugin=mysql_native_password'
        networks:
          - app-network
    

    db 서비스 정의에는 다음 옵션이 포함됩니다.

    • image: Compose에게 컨테이너를 생성하기 위해 가져올 이미지를 알려줍니다. Dockerfile 모범 사례를 고정하고 있습니다.
    • container_name: 컨테이너의 이름을 지정합니다.
    • restart: 컨테이너 재시작 정책을 정의합니다. 기본값은 no이지만 수동으로 중지하지 않는 한 컨테이너를 다시 시작하도록 설정했습니다.
    • env_file: 이 옵션은 Compose에게 빌드 컨텍스트에 있는 .env라는 파일에서 환경 변수를 추가할 것임을 알려줍니다. 이 경우 빌드 컨텍스트는 현재 디렉터리입니다.
    • environment: 이 옵션을 사용하면 .env 파일에 정의된 환경 변수 외에 추가 환경 변수를 추가할 수 있습니다. 애플리케이션 데이터베이스의 이름을 제공하기 위해 MYSQL_DATABASE 변수를 wordpress와 동일하게 설정합니다. 이는 민감하지 않은 정보이므로 docker-compose.yml 파일에 직접 포함할 수 있습니다.
    • volumes: 여기에서 dbdata라는 명명된 볼륨을 컨테이너의 /var/lib/mysql 디렉토리에 마운트합니다. 이것은 대부분의 배포판에서 MySQL의 표준 데이터 디렉토리입니다.
    • command: 이 옵션은 기본 MySQL의 최신 인증 기본값을 재정의하는 명령을 지정합니다. 애플리케이션 데이터베이스 사용자를 인증하려면 이 조정을 수행해야 합니다.
    • networks: 애플리케이션 서비스가 app-network 네트워크에 가입하도록 지정하며 파일 하단에서 정의합니다.

    다음으로 db 서비스 정의 아래에 wordpress 애플리케이션 서비스에 대한 정의를 추가합니다.

    ...
      wordpress:
        depends_on: 
          - db
        image: wordpress:5.1.1-fpm-alpine
        container_name: wordpress
        restart: unless-stopped
        env_file: .env
        environment:
          - WORDPRESS_DB_HOST=db:3306
          - WORDPRESS_DB_USER=$MYSQL_USER
          - WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD
          - WORDPRESS_DB_NAME=wordpress
        volumes:
          - wordpress:/var/www/html
        networks:
          - app-network
    

    이 서비스 정의에서는 db 서비스에서 했던 것처럼 컨테이너의 이름을 지정하고 다시 시작 정책을 정의합니다. 또한 이 컨테이너에 특정한 몇 가지 옵션을 추가합니다.

    • depends_on: 이 옵션은 컨테이너가 db 컨테이너 다음에 시작하는 wordpress 컨테이너와 함께 종속성 순서대로 시작되도록 합니다. 귀하의 WordPress 애플리케이션은 애플리케이션 데이터베이스 및 사용자의 존재에 의존하므로 이 종속성 순서를 표현하면 애플리케이션이 올바르게 시작될 수 있습니다.
    • image: 이 설정에서는 Docker Hub WordPress 이미지 페이지를 사용하고 있습니다.
    • env_file: 애플리케이션 데이터베이스 사용자 및 비밀번호를 정의한 .env 파일에서 값을 가져오도록 다시 지정합니다.
    • environment: 여기서는 .env 파일에서 정의한 값을 사용하지만 WordPress 이미지가 예상하는 변수 이름에 할당합니다. < 코드>WORDPRESS_DB_USER 및 WORDPRESS_DB_PASSWORD. 또한 MySQL의 기본 포트인 3306에서 액세스할 수 있는 db 컨테이너에서 실행되는 MySQL 서버가 될 WORDPRESS_DB_HOST도 정의합니다. WORDPRESS_DB_NAMEMYSQL_DATABASE: wordpress에 대한 MySQL 서비스 정의에 지정한 것과 동일한 값입니다.
    • volumes: wordpress라는 명명된 볼륨을 WordPress 이미지에 의해 생성된 /var/www/html 마운트 지점에 마운트하고 있습니다. 이러한 방식으로 명명된 볼륨을 사용하면 애플리케이션 코드를 다른 컨테이너와 공유할 수 있습니다.
    • networks: 또한 wordpress 컨테이너를 app-network 네트워크에 추가합니다.

    다음으로 wordpress 애플리케이션 서비스 정의 아래에 webserver Nginx 서비스에 대한 다음 정의를 추가합니다.

    ...
      webserver:
        depends_on:
          - wordpress
        image: nginx:1.15.12-alpine
        container_name: webserver
        restart: unless-stopped
        ports:
          - "80:80"
        volumes:
          - wordpress:/var/www/html
          - ./nginx-conf:/etc/nginx/conf.d
          - certbot-etc:/etc/letsencrypt
        networks:
          - app-network
    

    여기에서 컨테이너의 이름을 지정하고 시작 순서대로 wordpress 컨테이너에 종속되게 만듭니다. alpine 이미지인 1.15.12-alpine Nginx 이미지도 사용하고 있습니다.

    이 서비스 정의에는 다음 옵션도 포함됩니다.

    • ports: 포트 80을 노출하여 1단계에서 nginx.conf 파일에 정의한 구성 옵션을 활성화합니다.
    • volumes: 여기에서는 명명된 볼륨과 바인드 마운트의 조합을 정의합니다.\n
      • wordpress:/var/www/html: WordPress 애플리케이션 코드를 /var/www/html 디렉토리에 마운트합니다. Nginx 서버 블록의root.
      • ./nginx-conf:/etc/nginx/conf.d: 이렇게 하면 호스트의 Nginx 구성 디렉터리를 컨테이너의 관련 디렉터리에 바인딩하여 변경 사항이 있는지 확인합니다. 호스트의 파일에 대한 데이터가 컨테이너에 반영됩니다.
      • certbot-etc:/etc/letsencrypt: 도메인에 대한 관련 Let’s Encrypt 인증서 및 키를 컨테이너의 적절한 디렉토리에 마운트합니다.

      또한 이 컨테이너를 app-network 네트워크에 추가했습니다.

      마지막으로 webserver 정의 아래에 certbot 서비스에 대한 마지막 서비스 정의를 추가합니다. 여기에 나열된 이메일 주소와 도메인 이름을 자신의 정보로 바꾸십시오.

        certbot:
          depends_on:
            - webserver
          image: certbot/certbot
          container_name: certbot
          volumes:
            - certbot-etc:/etc/letsencrypt
            - wordpress:/var/www/html
          command: certonly --webroot --webroot-path=/var/www/html --email sammy@your_domain --agree-tos --no-eff-email --staging -d your_domain -d www.your_domain
      

      이 정의는 Compose에게 Docker 허브에서 certbot/certbot 이미지를 가져오도록 지시합니다. 또한 명명된 볼륨을 사용하여 certbot-etc의 도메인 인증서 및 키와 wordpress의 애플리케이션 코드를 포함하여 Nginx 컨테이너와 리소스를 공유합니다.

      다시, webserver 서비스가 실행되면 certbot 컨테이너가 시작되도록 지정하기 위해 depends_on을 사용했습니다.

      컨테이너의 기본 certbot 명령과 함께 실행할 하위 명령을 지정하는 command 옵션도 포함했습니다. certonly 하위 명령은 다음 옵션을 사용하여 인증서를 가져옵니다.

      • --webroot: 인증을 위해 webroot 폴더에 파일을 배치하기 위해 webroot 플러그인을 사용하도록 Certbot에 지시합니다. 이 플러그인은 HTTP 요청을 사용하여 Certbot이 주어진 도메인 이름에 응답하는 서버의 리소스에 액세스할 수 있음을 증명하는 HTTP-01 유효성 검사 방법에 의존합니다.
      • --webroot-path: 웹루트 디렉토리의 경로를 지정합니다.
      • --email: 등록 및 복구를 위해 선호하는 이메일입니다.
      • --agree-tos: 이것은 귀하가 ACME의 가입자 계약에 동의함을 지정합니다.
      • --no-eff-email: 전자 프론티어 재단(EFF)과 이메일을 공유하고 싶지 않다고 Certbot에 알립니다. 원하는 경우 생략해도 됩니다.
      • --staging: 테스트 인증서를 얻기 위해 Let's Encrypt의 스테이징 환경을 사용하고 싶다고 Certbot에 알립니다. 이 옵션을 사용하면 구성 옵션을 테스트하고 가능한 도메인 요청 제한을 피할 수 있습니다. 이러한 제한에 대한 자세한 내용은 Let's Encrypt의 속도 제한 문서를 참조하세요.
      • -d: 요청에 적용할 도메인 이름을 지정할 수 있습니다. 이 경우 your_domainwww.your_domain을 포함했습니다. 이를 자신의 도메인으로 교체해야 합니다.

      certbot 서비스 정의 아래에 네트워크 및 볼륨 정의를 추가합니다.

      ...
      volumes:
        certbot-etc:
        wordpress:
        dbdata:
      
      networks:
        app-network:
          driver: bridge  
      

      최상위 volumes 키는 볼륨 certbot-etc, wordpressdbdata를 정의합니다. Docker가 볼륨을 생성할 때 볼륨의 내용은 Docker가 관리하는 호스트 파일 시스템 /var/lib/docker/volumes/의 디렉터리에 저장됩니다. 그러면 각 볼륨의 내용이 이 디렉터리에서 해당 볼륨을 사용하는 컨테이너로 마운트됩니다. 이러한 방식으로 컨테이너 간에 코드와 데이터를 공유할 수 있습니다.

      사용자 정의 브리지 네트워크 app-network는 컨테이너가 동일한 Docker 데몬 호스트에 있기 때문에 컨테이너 간 통신을 가능하게 합니다. 이렇게 하면 포트를 외부에 노출하지 않고 동일한 브리지 네트워크에 있는 컨테이너 사이의 모든 포트를 열므로 애플리케이션 내 트래픽과 통신이 간소화됩니다. 따라서 db, wordpresswebserver 컨테이너는 서로 통신할 수 있으며 포트 80 애플리케이션에 대한 프런트 엔드 액세스용입니다.

      다음은 전체 docker-compose.yml 파일입니다.

      version: '3'
      
      services:
        db:
          image: mysql:8.0
          container_name: db
          restart: unless-stopped
          env_file: .env
          environment:
            - MYSQL_DATABASE=wordpress
          volumes: 
            - dbdata:/var/lib/mysql
          command: '--default-authentication-plugin=mysql_native_password'
          networks:
            - app-network
      
        wordpress:
          depends_on: 
            - db
          image: wordpress:5.1.1-fpm-alpine
          container_name: wordpress
          restart: unless-stopped
          env_file: .env
          environment:
            - WORDPRESS_DB_HOST=db:3306
            - WORDPRESS_DB_USER=$MYSQL_USER
            - WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD
            - WORDPRESS_DB_NAME=wordpress
          volumes:
            - wordpress:/var/www/html
          networks:
            - app-network
      
        webserver:
          depends_on:
            - wordpress
          image: nginx:1.15.12-alpine
          container_name: webserver
          restart: unless-stopped
          ports:
            - "80:80"
          volumes:
            - wordpress:/var/www/html
            - ./nginx-conf:/etc/nginx/conf.d
            - certbot-etc:/etc/letsencrypt
          networks:
            - app-network
      
        certbot:
          depends_on:
            - webserver
          image: certbot/certbot
          container_name: certbot
          volumes:
            - certbot-etc:/etc/letsencrypt
            - wordpress:/var/www/html
          command: certonly --webroot --webroot-path=/var/www/html --email sammy@your_domain --agree-tos --no-eff-email --staging -d your_domain -d www.your_domain
      
      volumes:
        certbot-etc:
        wordpress:
        dbdata:
      
      networks:
        app-network:
          driver: bridge  
      

      편집을 마치면 파일을 저장하고 닫습니다.

      서비스 정의가 준비되면 컨테이너를 시작하고 인증서 요청을 테스트할 준비가 된 것입니다.

      4단계 - SSL 인증서 및 자격 증명 얻기

      지정한 순서대로 컨테이너를 만들고 실행하는 docker-compose up 명령으로 컨테이너를 시작합니다. -d 플래그를 추가하면 명령이 백그라운드에서 db, wordpresswebserver 컨테이너를 실행합니다. :

      1. docker-compose up -d

      다음 출력은 서비스가 생성되었음을 확인합니다.

      Output
      Creating db ... done Creating wordpress ... done Creating webserver ... done Creating certbot ... done

      docker-compose ps를 사용하여 서비스 상태를 확인합니다.

      1. docker-compose ps

      완료되면 db, wordpresswebserver 서비스가 Up되고 certbot이 됩니다. 컨테이너는 0 상태 메시지와 함께 종료됩니다.

      Output
      Name Command State Ports ------------------------------------------------------------------------- certbot certbot certonly --webroot ... Exit 0 db docker-entrypoint.sh --def ... Up 3306/tcp, 33060/tcp webserver nginx -g daemon off; Up 0.0.0.0:80->80/tcp wordpress docker-entrypoint.sh php-fpm Up 9000/tcp

      db, wordpress 또는 webserverState 열의 Up 이외의 항목 > 서비스 또는 certbot 컨테이너에 대한 0 이외의 종료 상태는 docker-compose 로그 로 서비스 로그를 확인해야 할 수도 있음을 의미합니다. 명령:

      1. docker-compose logs service_name

      이제 docker-compose exec를 사용하여 인증서가 webserver 컨테이너에 마운트되었는지 확인할 수 있습니다.

      1. docker-compose exec webserver ls -la /etc/letsencrypt/live

      인증서 요청이 성공하면 다음과 같이 출력됩니다.

      Output
      total 16 drwx------ 3 root root 4096 May 10 15:45 . drwxr-xr-x 9 root root 4096 May 10 15:45 .. -rw-r--r-- 1 root root 740 May 10 15:45 README drwxr-xr-x 2 root root 4096 May 10 15:45 your_domain

      이제 요청이 성공할 것임을 알았으므로 certbot 서비스 정의를 편집하여 --staging 플래그를 제거할 수 있습니다.

      docker-compose.yml을 엽니다.

      1. nano docker-compose.yml

      certbot 서비스 정의가 있는 파일 섹션을 찾고 command 옵션의 --staging 플래그를 - -force-renewal 플래그, 기존 인증서와 동일한 도메인을 사용하여 새 인증서를 요청하려고 Certbot에 알립니다. 다음은 업데이트된 플래그가 있는 certbot 서비스 정의입니다.

      ...
        certbot:
          depends_on:
            - webserver
          image: certbot/certbot
          container_name: certbot
          volumes:
            - certbot-etc:/etc/letsencrypt
            - certbot-var:/var/lib/letsencrypt
            - wordpress:/var/www/html
          command: certonly --webroot --webroot-path=/var/www/html --email sammy@your_domain --agree-tos --no-eff-email --force-renewal -d your_domain -d www.your_domain
      ...
      

      이제 docker-compose up을 실행하여 certbot 컨테이너를 다시 생성할 수 있습니다. 또한 --no-deps 옵션을 포함하여 webserver 서비스가 이미 실행 중이므로 시작을 건너뛸 수 있음을 Compose에 알립니다.

      1. docker-compose up --force-recreate --no-deps certbot

      다음 출력은 인증서 요청이 성공했음을 나타냅니다.

      Output
      Recreating certbot ... done Attaching to certbot certbot | Saving debug log to /var/log/letsencrypt/letsencrypt.log certbot | Plugins selected: Authenticator webroot, Installer None certbot | Renewing an existing certificate certbot | Performing the following challenges: certbot | http-01 challenge for your_domain certbot | http-01 challenge for www.your_domain certbot | Using the webroot path /var/www/html for all unmatched domains. certbot | Waiting for verification... certbot | Cleaning up challenges certbot | IMPORTANT NOTES: certbot | - Congratulations! Your certificate and chain have been saved at: certbot | /etc/letsencrypt/live/your_domain/fullchain.pem certbot | Your key file has been saved at: certbot | /etc/letsencrypt/live/your_domain/privkey.pem certbot | Your cert will expire on 2019-08-08. To obtain a new or tweaked certbot | version of this certificate in the future, simply run certbot certbot | again. To non-interactively renew *all* of your certificates, run certbot | "certbot renew" certbot | - Your account credentials have been saved in your Certbot certbot | configuration directory at /etc/letsencrypt. You should make a certbot | secure backup of this folder now. This configuration directory will certbot | also contain certificates and private keys obtained by Certbot so certbot | making regular backups of this folder is ideal. certbot | - If you like Certbot, please consider supporting our work by: certbot | certbot | Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate certbot | Donating to EFF: https://eff.org/donate-le certbot | certbot exited with code 0

      인증서가 있으면 SSL을 포함하도록 Nginx 구성을 수정할 수 있습니다.

      5단계 - 웹 서버 구성 및 서비스 정의 수정

      Nginx 구성에서 SSL을 활성화하려면 HTTPS에 대한 HTTP 리디렉션 추가, SSL 인증서 및 키 위치 지정, 보안 매개변수 및 헤더 추가가 필요합니다.

      이러한 추가 사항을 포함하도록 webserver 서비스를 다시 생성할 예정이므로 지금 중지할 수 있습니다.

      1. docker-compose stop webserver

      구성 파일을 수정하기 전에 curl을 사용하여 Certbot에서 권장 Nginx 보안 매개변수를 가져옵니다.

      1. curl -sSLo nginx-conf/options-ssl-nginx.conf https://raw.githubusercontent.com/certbot/certbot/master/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf

      이 명령은 이러한 매개 변수를 nginx-conf 디렉터리에 있는 options-ssl-nginx.conf라는 파일에 저장합니다.

      다음으로 이전에 생성한 Nginx 구성 파일을 제거합니다.

      1. rm nginx-conf/nginx.conf

      다른 버전의 파일을 만들고 엽니다.

      1. nano nginx-conf/nginx.conf

      다음 코드를 파일에 추가하여 HTTP를 HTTPS로 리디렉션하고 SSL 자격 증명, 프로토콜 및 보안 헤더를 추가합니다. your_domain을 자신의 도메인으로 교체해야 합니다.

      server {
              listen 80;
              listen [::]:80;
      
              server_name your_domain www.your_domain;
      
              location ~ /.well-known/acme-challenge {
                      allow all;
                      root /var/www/html;
              }
      
              location / {
                      rewrite ^ https://$host$request_uri? permanent;
              }
      }
      
      server {
              listen 443 ssl http2;
              listen [::]:443 ssl http2;
              server_name your_domain www.your_domain;
      
              index index.php index.html index.htm;
      
              root /var/www/html;
      
              server_tokens off;
      
              ssl_certificate /etc/letsencrypt/live/your_domain/fullchain.pem;
              ssl_certificate_key /etc/letsencrypt/live/your_domain/privkey.pem;
      
              include /etc/nginx/conf.d/options-ssl-nginx.conf;
      
              add_header X-Frame-Options "SAMEORIGIN" always;
              add_header X-XSS-Protection "1; mode=block" always;
              add_header X-Content-Type-Options "nosniff" always;
              add_header Referrer-Policy "no-referrer-when-downgrade" always;
              add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
              # add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
              # enable strict transport security only if you understand the implications
      
              location / {
                      try_files $uri $uri/ /index.php$is_args$args;
              }
      
              location ~ \.php$ {
                      try_files $uri =404;
                      fastcgi_split_path_info ^(.+\.php)(/.+)$;
                      fastcgi_pass wordpress:9000;
                      fastcgi_index index.php;
                      include fastcgi_params;
                      fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                      fastcgi_param PATH_INFO $fastcgi_path_info;
              }
      
              location ~ /\.ht {
                      deny all;
              }
              
              location = /favicon.ico { 
                      log_not_found off; access_log off; 
              }
              location = /robots.txt { 
                      log_not_found off; access_log off; allow all; 
              }
              location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ {
                      expires max;
                      log_not_found off;
              }
      }
      

      HTTP 서버 블록은 .well-known/acme-challenge 디렉토리에 대한 Certbot 갱신 요청의 웹루트를 지정합니다. 또한 루트 디렉터리에 대한 HTTP 요청을 HTTPS로 보내는 재작성 지시문도 포함합니다.

      HTTPS 서버 블록은 sslhttp2를 활성화합니다. HTTP/2가 HTTP 프로토콜에서 반복되는 방식과 웹사이트 성능에 대해 얻을 수 있는 이점에 대해 자세히 알아보려면 Ubuntu 18.04에서 HTTP/2 지원으로 Nginx를 설정하는 방법 소개를 읽어보세요.

      이 블록에는 nginx-conf/options-ssl-nginx.conf에 저장한 권장 Certbot 보안 매개변수와 함께 SSL 인증서 및 키 위치도 포함됩니다.

      또한 "사전 로드\ 기능과 같은 항목에 대해 A 등급을 받을 수 있는 몇 가지 보안 헤더가 포함되어 있습니다.

      rootindex 지시문도 1단계에서 설명한 WordPress 관련 위치 블록의 나머지 부분과 마찬가지로 이 블록에 있습니다.

      편집이 완료되면 파일을 저장하고 닫습니다.

      webserver 서비스를 다시 생성하기 전에 webserver 서비스 정의에 443 포트 매핑을 추가해야 합니다.

      docker-compose.yml 파일을 엽니다.

      1. nano docker-compose.yml

      webserver 서비스 정의에서 다음 포트 매핑을 추가합니다.

      ...
        webserver:
          depends_on:
            - wordpress
          image: nginx:1.15.12-alpine
          container_name: webserver
          restart: unless-stopped
          ports:
            - "80:80"
            - "443:443"
          volumes:
            - wordpress:/var/www/html
            - ./nginx-conf:/etc/nginx/conf.d
            - certbot-etc:/etc/letsencrypt
          networks:
            - app-network
      

      편집 후 완전한 docker-compose.yml 파일은 다음과 같습니다.

      version: '3'
      
      services:
        db:
          image: mysql:8.0
          container_name: db
          restart: unless-stopped
          env_file: .env
          environment:
            - MYSQL_DATABASE=wordpress
          volumes: 
            - dbdata:/var/lib/mysql
          command: '--default-authentication-plugin=mysql_native_password'
          networks:
            - app-network
      
        wordpress:
          depends_on: 
            - db
          image: wordpress:5.1.1-fpm-alpine
          container_name: wordpress
          restart: unless-stopped
          env_file: .env
          environment:
            - WORDPRESS_DB_HOST=db:3306
            - WORDPRESS_DB_USER=$MYSQL_USER
            - WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD
            - WORDPRESS_DB_NAME=wordpress
          volumes:
            - wordpress:/var/www/html
          networks:
            - app-network
      
        webserver:
          depends_on:
            - wordpress
          image: nginx:1.15.12-alpine
          container_name: webserver
          restart: unless-stopped
          ports:
            - "80:80"
            - "443:443"
          volumes:
            - wordpress:/var/www/html
            - ./nginx-conf:/etc/nginx/conf.d
            - certbot-etc:/etc/letsencrypt
          networks:
            - app-network
      
        certbot:
          depends_on:
            - webserver
          image: certbot/certbot
          container_name: certbot
          volumes:
            - certbot-etc:/etc/letsencrypt
            - wordpress:/var/www/html
          command: certonly --webroot --webroot-path=/var/www/html --email sammy@your_domain --agree-tos --no-eff-email --force-renewal -d your_domain -d www.your_domain
      
      volumes:
        certbot-etc:
        wordpress:
        dbdata:
      
      networks:
        app-network:
          driver: bridge  
      

      편집을 마치면 파일을 저장하고 닫습니다.

      webserver 서비스를 다시 만듭니다.

      1. docker-compose up -d --force-recreate --no-deps webserver

      docker-compose ps로 서비스를 확인하십시오.

      1. docker-compose ps

      출력은 db, wordpresswebserver 서비스가 실행 중임을 나타내야 합니다.

      Output
      Name Command State Ports ---------------------------------------------------------------------------------------------- certbot certbot certonly --webroot ... Exit 0 db docker-entrypoint.sh --def ... Up 3306/tcp, 33060/tcp webserver nginx -g daemon off; Up 0.0.0.0:443->443/tcp, 0.0.0.0:80->80/tcp wordpress docker-entrypoint.sh php-fpm Up 9000/tcp

      컨테이너가 실행 중이면 웹 인터페이스를 통해 WordPress 설치를 완료할 수 있습니다.

      6단계 - 웹 인터페이스를 통해 설치 완료

      컨테이너가 실행 중인 상태에서 WordPress 웹 인터페이스를 통해 설치를 완료합니다.

      웹 브라우저에서 서버의 도메인으로 이동합니다. your_domain을 자신의 도메인 이름으로 대체해야 합니다.

      https://your_domain
      

      사용하려는 언어를 선택하십시오:

      계속을 클릭하면 사이트 이름과 사용자 이름을 선택해야 하는 기본 설정 페이지로 이동합니다. 여기에서 기억하기 쉬운 사용자 이름("admin”이 아닌)과 강력한 암호를 선택하는 것이 좋습니다. WordPress에서 자동으로 생성하는 암호를 사용하거나 직접 만들 수 있습니다.

      마지막으로 이메일 주소를 입력하고 검색 엔진이 귀하의 사이트를 인덱싱하지 못하도록 할지 여부를 결정해야 합니다.

      페이지 하단의 WordPress 설치를 클릭하면 로그인 프롬프트가 표시됩니다.

      로그인하면 WordPress 관리 대시보드에 액세스할 수 있습니다.

      WordPress 설치가 완료되면 SSL 인증서가 자동으로 갱신되도록 조치를 취할 수 있습니다.

      7단계 - 인증서 갱신

      Let’s Encrypt 인증서는 90일 동안 유효합니다. 만료되지 않도록 자동 갱신 프로세스를 설정할 수 있습니다. 이를 수행하는 한 가지 방법은 cron 스케줄링 유틸리티로 작업을 생성하는 것입니다. 다음 예에서는 cron 작업을 생성하여 인증서를 갱신하고 Nginx 구성을 다시 로드하는 스크립트를 주기적으로 실행합니다.

      먼저 ssl_renew.sh라는 스크립트를 엽니다.

      1. nano ssl_renew.sh

      다음 코드를 스크립트에 추가하여 인증서를 갱신하고 웹 서버 구성을 다시 로드하십시오. 여기서 예시 사용자 이름을 루트가 아닌 사용자 이름으로 바꾸십시오.

      #!/bin/bash
      
      COMPOSE="/usr/local/bin/docker-compose --no-ansi"
      DOCKER="/usr/bin/docker"
      
      cd /home/sammy/wordpress/
      $COMPOSE run certbot renew --dry-run && $COMPOSE kill -s SIGHUP webserver
      $DOCKER system prune -af
      

      이 스크립트는 먼저 COMPOSE라는 변수에 docker-compose 바이너리를 할당하고 --no-ansi 옵션을 지정합니다. ANSI 제어 문자가 없는docker-compose 명령. 그런 다음 docker 바이너리로 동일한 작업을 수행합니다. 마지막으로 ~/wordpress 프로젝트 디렉토리로 변경하고 다음 docker-compose 명령을 실행합니다.

      • docker-compose run: certbot 컨테이너를 시작하고 certbot에 제공된 명령을 재정의합니다. 서비스 정의. certonly 하위 명령을 사용하는 대신 만료가 임박한 인증서를 갱신하는 renew 하위 명령이 사용됩니다. 또한 스크립트를 테스트하기 위한 --dry-run 옵션도 포함되어 있습니다.
      • SIGHUPwebserver 컨테이너에 신호를 보내 Nginx 구성을 다시 로드합니다.

      그런 다음 docker system prune을 실행하여 사용하지 않는 모든 컨테이너와 이미지를 제거합니다.

      편집을 마치면 파일을 닫습니다. 다음 명령을 사용하여 실행 가능하게 만드십시오.

      1. chmod +x ssl_renew.sh

      다음으로 루트 crontab 파일을 열어 지정된 간격으로 갱신 스크립트를 실행합니다.

      sudo crontab -e 
      

      이 파일을 처음 편집하는 경우 편집기를 선택하라는 메시지가 표시됩니다.

      Output
      no crontab for root - using an empty one Select an editor. To change later, run 'select-editor'. 1. /bin/nano <---- easiest 2. /usr/bin/vim.basic 3. /usr/bin/vim.tiny 4. /bin/ed Choose 1-4 [1]: ...

      이 파일 맨 아래에 다음 행을 추가하십시오.

      ...
      */5 * * * * /home/sammy/wordpress/ssl_renew.sh >> /var/log/cron.log 2>&1
      

      이렇게 하면 작업 간격이 5분마다 설정되므로 갱신 요청이 의도한 대로 작동하는지 여부를 테스트할 수 있습니다. 로그 파일 cron.log는 작업의 관련 출력을 기록하기 위해 생성됩니다.

      5분 후 cron.log를 확인하여 갱신 요청이 성공했는지 확인합니다.

      1. tail -f /var/log/cron.log

      다음 출력은 성공적인 갱신을 확인합니다.

      Output
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ** DRY RUN: simulating 'certbot renew' close to cert expiry ** (The test certificates below have not been saved.) Congratulations, all renewals succeeded. The following certs have been renewed: /etc/letsencrypt/live/your_domain/fullchain.pem (success) ** DRY RUN: simulating 'certbot renew' close to cert expiry ** (The test certificates above have not been saved.) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      터미널에 CTRL+C를 입력하여 종료합니다.

      crontab 파일을 수정하여 매일 간격을 설정할 수 있습니다. 예를 들어 매일 정오에 스크립트를 실행하려면 파일의 마지막 줄을 다음과 같이 수정합니다.

      ...
      0 12 * * * /home/sammy/wordpress/ssl_renew.sh >> /var/log/cron.log 2>&1
      

      또한 ssl_renew.sh 스크립트에서 --dry-run 옵션을 제거해야 합니다.

      #!/bin/bash
      
      COMPOSE="/usr/local/bin/docker-compose --no-ansi"
      DOCKER="/usr/bin/docker"
      
      cd /home/sammy/wordpress/
      $COMPOSE run certbot renew && $COMPOSE kill -s SIGHUP webserver
      $DOCKER system prune -af
      

      귀하의 cron 작업은 자격이 있을 때 인증서를 갱신하여 Let’s Encrypt 인증서가 만료되지 않도록 합니다. Logrotate 유틸리티로 로그 회전을 설정하여 로그 파일을 회전 및 압축할 수도 있습니다.

      결론

      이 자습서에서는 Docker Compose를 사용하여 Nginx 웹 서버로 WordPress 설치를 생성했습니다. 이 워크플로의 일부로 WordPress 사이트와 연결하려는 도메인에 대한 TLS/SSL 인증서를 얻었습니다. 또한 필요할 때 이러한 인증서를 갱신하기 위해 cron 작업을 생성했습니다.

      사이트 성능 및 중복성을 개선하기 위한 추가 단계로 WordPress 자산 제공 및 백업에 대한 다음 문서를 참조할 수 있습니다.

      • DigitalOcean Spaces CDN을 사용하여 WordPress 자산 전달 속도를 높이는 방법
      • WordPress 사이트를 Spaces에 백업하는 방법.
      • DigitalOcean Spaces에 WordPress 자산을 저장하는 방법.

      Kubernetes를 사용하여 컨테이너화된 워크플로를 탐색하는 데 관심이 있는 경우 다음을 확인할 수도 있습니다.

      • Helm을 사용하여 Kubernetes에서 MySQL로 WordPress를 설정하는 방법.