SSL을 지원하는 WordPress docker-compose.yaml

wordpress를 사용하기 위해 서버를 구성하며 진행했던 내용 누군가에게 도움이 되었으면 좋겠다는 바램을 담아 기록으로 남겨봅니다.

Oracle Free Trial 서버를 만든 지 한참이 지났지만 넉넉하지 못한 서버 사양으로 활용도를 찾지 못하고 있던 와중에 wordpress로 블로그를 구축해서 사용하는 사례를 알게 되었고, 직접 구현해 보면서 고민하고 알게 된 내용입니다.

현재 이 wordpress가 돌고 있는 서버는 Oracle Free Trial에서 평생 무료 정책으로 계정당 2개를 제공해주는 vm 중 1개로 Ubuntu Linux 22.04 LTS 버전이 설치되어 있습니다.

AMD EPYC 7551 32-Core Processor CPU 2Core와 1GB의 메모리, 100GB의 디스크로 구성된 서버라 간단한 웹서버나 DB서버 등으로 활용이 가능한데, wordpress 정도를 구성하는데는 충분한 사양인 것 같습니다.

wordpress를 구성하기 위해서는 크게 2가지 모듈이 필요합니다.

  1. wordpress (php가 설치된 웹서버 필요 ex.apache, nginx)
  2. database (일반적으로 MySQL, mariaDB)

각각 서버에 직접 설치 및 구성도 가능하지만 Docker를 활용하면 아주 간단하게 구성이 가능한데, 1가지 문제가 있습니다.

wordpress 컨테이너가 동작하는 웹서버는 nginx혹은 apache로 구현 된 경우가 많은데 기본적으로 SSL(https)를 지원하지 않기 때문에 요즘 많이 사용하는 chrome같은 브라우저에서 빨간 창을 보여주며 접근을 막는 상황이 발생하게 되죠.

이 문제를 해결하려면 서버 IP에 해당하는 도메인 생성 및 도메인에 맞는 SSL인증서를 발급받아 웹서버에 등록해야 하는데요

이런 일련의 과정을 1개의 docker-compose.yaml 파일로 정의 해서 바로 사용이 가능한 방법이 있어 그 방법을 사용하여 구성하였습니다.

서버 환경설정(docker환경 구성, 방화벽, 도메인 등록)은 이번 포스팅에서는 언급하지 않고 docker-compose.yaml 파일을 소개하는데 집중하고 관련 내용은 추후 하나하나 포스팅을 올려보도록 할께요.

docker-compose.yaml

version: "3.8"

services:
  # NginxProxy 가상 호스트를 관리하는 컨테이너
  nginx-proxy:
    image: jwilder/nginx-proxy:latest
    container_name: nginx-proxy
    privileged: true
    ports:
      - "80:80"
      - "443:443"
    environment:
      - DEFAULT_HOST=example.com  # 사용 domain
    volumes:
      - proxy:/etc/nginx/vhost.d
      - proxy:/usr/share/nginx/html
      - ./nginx-proxy/conf.d/custom_proxy_settings.conf:/etc/nginx/conf.d/custom_proxy_settings.conf  # nginx 설정 파일 mount
      - ./nginx-proxy/logs:/var/log/nginx  # Docker 컨테이너 내부의 apache 설정파일 mount
      - /var/run/docker.sock:/tmp/docker.sock:ro
      - ./certs:/etc/nginx/certs:ro
    restart: always
    networks:
      - app-net
      - default
    labels:
      com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy: ""

  # SSL 인증서를 관리하는 컨테이너 (Let's Encrypt)
  letsencrypt:
    image: jrcs/letsencrypt-nginx-proxy-companion
    container_name: lets-encrypt
    restart: always
    depends_on:
      - nginx-proxy
    volumes:
      - proxy:/etc/nginx/vhost.d
      - proxy:/usr/share/nginx/html
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./certs:/etc/nginx/certs:rw
    environment:
      - NGINX_PROXY_CONTAINER=nginx-proxy
    networks:
      - app-net
      - default

  # WordPress 컨테이너
  wordpress:
    build: 
      context: ./Php
      dockerfile: Dockerfile
    container_name: wordpress
    depends_on:
      - wordpressdb
    restart: always
    expose:
      - 80
      - 443
    environment:
      WORDPRESS_DB_HOST: wordpressdb
      WORDPRESS_DB_USER: wp_user
      WORDPRESS_DB_PASSWORD: password # 데이터베이스의 비밀번호
      WORDPRESS_DB_NAME: wordpress
      VIRTUAL_HOST: example.com  # 사용 domain
      VIRTUAL_PORT: 80
      LETSENCRYPT_HOST: example.com  # 사용 domain
      LETSENCRYPT_EMAIL: info@example.com # e-mail 주소
    volumes:
      - ./wordpress/html:/var/www/html  # wordpress 소스코드 폴더 mount
      - ./wordpress/log:/var/log/apache2  # Docker 컨테이너 내부의 apache 설정파일 mount
      - ./Php/php.ini:/usr/local/etc/php/php.ini # PHP 설정파일 mouunt
    networks:
      - app-net
      - default

  # wordpress가 사용할 데이터베이스 컨테이너
  wordpressdb:
    image: mariadb
    restart: always
    volumes:
      - ./wp_mariadb/db_data:/docker-entrypoint-initdb.d
      - ./wp_mariadb/data:/var/lib/mysql
      - ./wp_mariadb/logs:/var/log/mysql
      - ./wp_mariadb/conf.d/my.cnf:/etc/mysql/conf.d/my.cnf
    expose:
      - 3306
    ports:
      - 3306:3306
    environment:
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wp_user
      MYSQL_PASSWORD: password # 데이터베이스 비밀번호
      MYSQL_ROOT_PASSWORD: root_password # 데이터베이스의 root 비밀번호
      TZ: Asia/Seoul
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
    networks:
      - app-net
      - default

  # phpMyAdmin 컨테이너
  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    depends_on:
      - wordpressdb
    restart: always
    expose:
      - 88
    ports:
      - 88:80
    volumes:
      - ./wp_phpmyadmin/sessions:/sessions
    environment:
      PMA_ARBITRARY: 1
      PMA_HOST: wordpressdb
      PMA_USER: root
      PMA_PASSWORD: root_password # 데이터베이스의 root 비밀번호
    networks:
      - app-net
      - default

# 컨테이너들이 사용할 공유 네트워크
networks:
  app-net:
    driver: bridge
# mount volumes
volumes:
  db_data:
  proxy:

간단히 설명하면 nginx-proxy는 가상호스트를 관리합니다.

‘example.com’에 접속하면 nginx-proxy가 wordpress 컨테이너로 연결 해 줍니다.

‘letsencrypt’는 SSL 인증서를 관리하고 wordpress 컨테이너가 ‘https’로 연결 해 줍니다.

wordpress는 wordpress 자체 컨테이너 입니다.

phpmyadmin은 phpMyAdmin이라는 도구가 동작하는 컨테이너로 서버의 88번 포트를 통해 접속됩니다.

정리하면 잘 알고 계시는 wordpress와 mariadb 구조에 nginx-proxy와 letsencrypt컨테이너를 더해서 SSL인증서가 등록된 nginx-proxy를 통해 wordpress에 접속하는 구조 정도라고 할 수 있겠네요.

여기에 추가로 docker-compose.yaml 파일내부에 정의 된 Dockerfile과 custom_proxy_setting.conf , php.ini 파일이 필요합니다.

Dockerfile

FROM wordpress:6.5.3-php8.1-apache

# Run apt command
RUN apt-get update \
    && apt-get install -y \
            g++ \
            libicu-dev \
            libpq-dev \
            libzip-dev \
            unzip \
            zip \
            zlib1g-dev \
            libonig-dev \
            vim

# CP php.ini
RUN cp /usr/local/etc/php/php.ini-development /usr/local/etc/php/php.ini

CMD ["apache2-foreground"]

custom_proxy_setting.conf

client_max_body_size 10g;
proxy_request_buffering off;

proxy_buffers 8 32K;
proxy_buffer_size 32k;
proxy_busy_buffers_size 64k;

파일의 업로드사이즈를 변경하여 세션이 너무 커지는 것을 막기 위한 설정으로 필요에 따라 적용하시면 되는 부분입니다.

php.ini

php.ini 파일은 원본 php.ini파일에서 업로드 파일 사이즈가 변경되어 있습니다.

디렉토리 구성

docker-compose.yml
nginx-proxy/
 conf.d/
  custom_proxy_settings.conf
Php/
  Dockerfile
  php.ini

docker-compose.yaml 파일이 위치한 workdpress를 설치할 경로에 위와 같은 구조로 파일을 배포해 주시면 됩니다.

서버에 해당 파일을 업로드 한 후 ‘docker compose up -d’ 명령으로 docker를 실행한 후 https://example.com으로 접속하면 wordpress 초기 설정 화면이 보이실 겁니다.

관련하여 컨테이너 내부에서 에러가 발생하는 경우 ‘wordpress/log’와 ‘nginx-proxy/logs’에 각각의 로그가 기록되어 있으니 확인 및 조치가 가능합니다.

여기까지 SSL을 지원하는 wordpress docker-compose.yaml에 대한 포스팅을 마치겠습니다.

서버설치 및 구성의 불편함이 없는 docker를 많이 활용하는 추세인데 https통신을 위해 SSL인증서 등록을 하는데 애를 먹는 분들이 많이 있을 것 같습니다. (저도 그랬고, 인터넷 검색을 통해 관련 내용을 찾아 일부 오류가 있는 부분을 수정하여 올려 드리는 부분입니다.) ‘nginx-proxy’와 ‘letsencrypt’ 컨테이너를 추가하여 SSL등록을 가능하게 하는 좋은 방법인 것 같아 기록을 남겨 봅니다.

Leave a Comment