Docker Compose로 워드프레스 올리기 - 실제로 막혔던 지점들
워드프레스를 직접 호스팅하려고 Docker Compose로 올렸습니다. 공식 이미지가 있어서 금방 끝날 줄 알았는데, 막힌 곳이 네 군데였습니다.
전부 "설치 가이드"에는 안 나오고 실제로 해봐야 만나는 것들이었습니다.
결론부터 — 구성과 함정
Caddy (리버스 프록시, 자동 HTTPS)
└─ WordPress (php-apache)
└─ MariaDB
└─ Redis (선택)| 막힌 지점 | 원인 |
|---|---|
| 첫 기동에서 DB 연결 실패 | depends_on 이 컨테이너 시작만 보고 넘어감 |
| 무한 리다이렉트 | 프록시 뒤에서 HTTPS를 인식 못 함 |
| 설정 바꿔도 반영 안 됨 | 바인드 마운트는 compose up -d 가 변경을 감지 못함 |
| 퍼머링크 전부 404 | .htaccess 가 없음 |
1. depends_on 만으로는 부족합니다
처음 쓴 설정입니다.
wordpress:
depends_on: [db]
"DB가 먼저 뜨고 워드프레스가 뜬다"고 생각했습니다. 실제로는 컨테이너가 "시작"되기만 하면 다음으로 넘어갑니다.
MariaDB는 처음 기동할 때 데이터 디렉토리를 초기화하는 데 시간이 걸립니다. 그동안 워드프레스가 접속을 시도하면 실패합니다.
healthcheck를 붙여 "실제로 준비될 때까지" 기다리게 해야 합니다.
db:
image: mariadb:11
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s
timeout: 5s
retries: 10
wordpress:
depends_on:
db:
condition: service_healthy # ← 이것
고친 뒤 로그를 보면 순서가 명확합니다.
Container db-1 Waiting
Container db-1 Healthy
Container wordpress-1 Starting
MariaDB 공식 이미지에는
healthcheck.sh가 들어 있습니다.
다른 이미지라면mysqladmin ping같은 걸 씁니다.
2. 프록시 뒤에서는 HTTPS를 알려줘야 합니다
Caddy가 HTTPS를 처리하고 워드프레스에는 HTTP로 넘깁니다. 그러면 워드프레스는 자기가 HTTP로 서비스된다고 착각합니다.
증상은 이렇습니다.
- 관리자 화면 CSS가 깨짐
https://로 들어갔는데http://로 링크가 생성됨- 심하면 무한 리다이렉트
프록시가 보내주는 헤더를 읽어서 알려줘야 합니다.
wordpress:
environment:
WORDPRESS_CONFIG_EXTRA: |
if (isset($$_SERVER['HTTP_X_FORWARDED_PROTO']) && $$_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
$$_SERVER['HTTPS'] = 'on';
}
$$는 Docker Compose에서$를 이스케이프한 것입니다.
한 개만 쓰면 compose가 자기 변수로 해석해 빈 값이 들어갑니다.
3. 바인드 마운트는 up -d 로 반영되지 않습니다
설정 파일을 이렇게 마운트해두고,
caddy:
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
파일을 고친 뒤 docker compose up -d 를 쳤습니다. 아무 일도 일어나지 않았습니다.
up -d 는 compose 파일의 변경을 보고 컨테이너를 다시 만듭니다. 마운트된 파일 내용이 바뀐 건 보지 않습니다.
docker compose restart caddy # 이렇게 해야 반영됩니다
docker compose ps 로 보면 Up 2 hours 라고 찍혀 있어서, 재시작된 줄 알고 넘어가기 쉽습니다. 가동 시간을 확인하는 습관이 필요합니다.
저는 이것 때문에 보안 설정이 적용 안 된 걸 모르고 지나갈 뻔했습니다.
프록시에 특정 경로를 차단하는 규칙을 넣고 up -d 를 쳤습니다. 그런데 확인해보니 여전히 열려 있었습니다. 규칙 문법이 틀린 줄 알고 한참 고쳤습니다. 결국 ps 를 다시 보니 가동 시간이 그대로였습니다. 컨테이너가 아예 재시작되지 않았던 겁니다.
restart 한 번으로 끝날 일이었습니다.
4. 퍼머링크가 전부 404
워드프레스 설정에서 고정주소를 /글제목/ 으로 바꿨는데 글 주소가 전부 404였습니다. 첫 페이지만 열렸습니다.
원인은 .htaccess 가 없어서였습니다. 모든 요청을 index.php 로 넘기는 규칙이 거기 들어 있습니다.
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
공식 이미지를 그냥 쓰면 워드프레스가 알아서 만들어 줍니다. 그런데 소스를 직접 가져다 쓰면 이 파일이 없습니다. 공식 배포 소스에는 포함돼 있지 않기 때문입니다.
저는 소스를 직접 관리하려고 구조를 바꾸다가 이걸 만났습니다.
바꾸기 전에는 멀쩡했으니 더 헷갈렸습니다.
5. 검증 — 눈으로 보지 말고 측정합니다
브라우저로 열어보면 "되네" 하고 넘어가게 됩니다. 명령으로 확인하면 확실합니다.
# 각 주소가 실제로 어떤 코드를 주는지
for u in / /글주소/ /wp-admin/; do
printf "%-16s " "$u"
curl -s -o /dev/null -w '%{http_code}\n' "http://서버주소$u"
done
기대값은 이렇습니다.
/ 200
/글주소/ 200 ← 404면 .htaccess 문제
/wp-admin/ 302 ← 로그인으로 보내는 것이니 정상컨테이너 상태도 함께 봅니다.
docker compose ps --format "table {{.Service}}\t{{.Status}}"
db 가 (healthy) 로 찍히는지 확인합니다.
정리
depends_on은 "시작"만 봅니다. DB는healthcheck+condition: service_healthy- 프록시 뒤에서는
X-Forwarded-Proto를 읽어 HTTPS를 알려줘야 합니다 - 마운트한 설정 파일은
restart가 필요합니다.up -d로는 안 됩니다 .htaccess가 없으면 퍼머링크가 전부 404입니다- 브라우저 대신
curl로 확인하세요. 상태 코드가 거짓말을 하지 않습니다