Ghost + MySQL + Nginx + SSL을 Docker Compose로 나의 블로그 완전 자동화하기
비개발자도 따라할 수 있는 Ghost 블로그 설치 가이드. Docker Compose로 Ghost, MySQL, Nginx, SSL까지 한번에 구성하는 방법을 상세히 설명합니다. 실전 예제를 기반으로 환경 설정부터 자동 HTTPS까지 전 과정 수록.
이 글에서는 Ghost 블로그를 MySQL 데이터베이스와 함께, Nginx Reverse Proxy 및 무료 SSL 인증서 발급 기능까지 포함해 도커(Docker) 기반으로 한 번에 구축하는 방법을 소개합니다. 도커 컴포즈 파일만 이해하면 어렵지 않게 따라할 수 있으며, 저 처럼 개발자가 아니어도 개인 블로그를 안정적으로 운영할 수 있는 환경을 마련할 수 있습니다.
1. 전체 구조 미리 보기
우리가 사용할 구성은 다음과 같습니다:
- Ghost: 블로그 엔진
- MySQL: Ghost에서 사용하는 데이터 저장소
- Nginx + Let's Encrypt: 자동 HTTPS 적용 프록시 서버
- Docker Compose: 위 구성 전체를 하나의 명령어로 실행
각 구성 요소는 서비스 단위로 격리되어 있고, 필요한 설정은 .env 파일을 통해 주입됩니다.
2. docker-compose.yml
version: '3.9'
services:
nginx-proxy:
image: nginxproxy/nginx-proxy
container_name: nginx-proxy
ports:
- 80:80
- 443:443
volumes:
- ./certs:/etc/nginx/certs:ro
- ./vhost:/etc/nginx/vhost.d
- ./html:/usr/share/nginx/html
- ./conf:/etc/nginx/conf.d
- /var/run/docker.sock:/tmp/docker.sock:ro
restart: unless-stopped
nginx-proxy-acme:
image: nginxproxy/acme-companion
container_name: nginx-proxy-acme
depends_on:
- nginx-proxy
environment:
NGINX_PROXY_CONTAINER: nginx-proxy
volumes:
- ./certs:/etc/nginx/certs:rw
- ./acme:/etc/acme.sh
- ./vhost:/etc/nginx/vhost.d
- ./html:/usr/share/nginx/html
- /var/run/docker.sock:/var/run/docker.sock:ro
restart: unless-stopped
ghost:
image: ghost:5
container_name: ghost
depends_on:
- db
environment:
NODE_ENV: production
url: https://${DOMAIN}
VIRTUAL_HOST: ${DOMAIN}
VIRTUAL_PORT: 2368
LETSENCRYPT_HOST: ${DOMAIN}
LETSENCRYPT_EMAIL: ${EMAIL}
MAIL__TRANSPORT: ${MAIL_TRANSPORT}
MAIL__OPTIONS__SERVICE: ${MAIL_SERVICE}
MAIL__OPTIONS__AUTH__USER: ${MAIL_USER}
MAIL__OPTIONS__AUTH__PASS: ${MAIL_PASS}
database__client: mysql
database__connection__host: db
database__connection__user: ${MYSQL_USER}
database__connection__password: ${MYSQL_PASSWORD}
database__connection__database: ${MYSQL_DATABASE}
volumes:
- ./ghost-data:/var/lib/ghost/content
restart: unless-stopped
db:
image: mysql:8.0.42
container_name: ghost-mysql
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
volumes:
- ./db-data:/var/lib/mysql
restart: unless-stopped
volumes:
ghost-data:
db-data:
certs:
vhost:
html:
acme:
conf:3. 서비스별 상세 설명
이제 초보자도 이해할 수 있게 서비스 단위로 분석합니다.
✅ 3.1 nginx-proxy: 리버스 프록시 역할
- 이미지:
nginxproxy/nginx-proxy - 역할: 외부에서 들어오는 HTTP/HTTPS 요청을 받아, 도메인 이름에 따라 적절한 컨테이너로 전달합니다.
- 포트 설정:
ports:
- 80:80
- 443:443→ 브라우저에서 http://(80) 또는 https://(443)로 접속하는 요청을 처리합니다.
- 볼륨
- ./certs:/etc/nginx/certs:ro
- ./vhost:/etc/nginx/vhost.d
- ./html:/usr/share/nginx/html
- ./conf:/etc/nginx/conf.d
- /var/run/docker.sock:/tmp/docker.sock:rocerts: SSL 인증서 저장소docker.sock: 컨테이너 정보를 읽어서 자동으로 프록시 설정 생성
✅ 3.2 nginx-proxy-acme: SSL 인증서 자동 발급
- 이미지:
nginxproxy/acme-companion - 역할: Let’s Encrypt SSL 인증서를 발급하고 자동 갱신합니다.
- 핵심 환경변수
- ./certs:/etc/nginx/certs:ro
- ./vhost:/etc/nginx/vhost.d
- ./html:/usr/share/nginx/html
- ./conf:/etc/nginx/conf.d
- /var/run/docker.sock:/tmp/docker.sock:ro→ 어느 컨테이너가 프록시인지 알려줍니다.
- 인증서 저장:
./certs경로에 저장
✅ 3.3 ghost: 블로그 본체
- 이미지:
ghost:5 - 핵심 환경변수
VIRTUAL_HOST: ${DOMAIN}
LETSENCRYPT_HOST: ${DOMAIN}
LETSENCRYPT_EMAIL: ${EMAIL}→ 이 값 덕분에 nginx-proxy와 acme-companion이 자동으로 SSL 발급 & 프록시 설정을 처리합니다.
- 데이터 저장:
volumes:
- ./ghost-data:/var/lib/ghost/content→ 블로그 콘텐츠는 ./ghost-data 폴더에 보존됩니다.
✅ 3.4 db: MySQL 데이터베이스
- 이미지:
mysql:8.0.42 - 환경변수:
MYSQL_ROOT_PASSWORD
MYSQL_DATABASE
MYSQL_USER
MYSQL_PASSWORD- 데이터 저장:
volumes:
- ./db-data:/var/lib/mysql4. .env 파일 작성
.env 파일을 만들어 민감정보를 외부에 노출하지 않습니다.
DOMAIN=blog.example.com
[email protected]
MYSQL_ROOT_PASSWORD=mysecret
MYSQL_DATABASE=ghostdb
MYSQL_USER=ghost
MYSQL_PASSWORD=ghostpw
MAIL_TRANSPORT=SMTP
MAIL_SERVICE=Gmail
[email protected]
MAIL_PASS=app-password5. 실행 방법
docker compose up -d-d옵션: 백그라운드 실행- 모든 서비스가 컨테이너로 실행되며, SSL 인증서는 자동 발급됩니다.
6. 첫 접속 & Ghost 초기 설정
브라우저에서 https://<DOMAIN>/ghost으로 접속 → Ghost 초기 설정 진행
메일 인증까지 설정하면 완벽한 블로그 운영 준비 완료!
✅ 초보자 포인트 요약
- 도커 볼륨 → 데이터는 컨테이너 삭제해도 보존됨
- 환경변수 (.env) → 설정 변경은
.env만 수정 - nginx-proxy + acme → SSL 인증서 완전 자동화
- docker compose up -d → 모든 서비스 한 줄로 실행