Code6OfficeBETA
초급 가이드 · 웹사이트 공개

웹사이트 공개 7편: Tunnel로 컨테이너 연결

웹사이트 공개 실습 7/14 · 가상 프로젝트 작은 작업실 기준입니다. example.com은 설명용 예약 도메인입니다. 실제 연결에는 본인 소유 도메인을 사용하세요.

이번 편의 목표와 사전 확인

6편의 도메인이 Active이고 http://localhost:4100에서 예제 앱이 열려야 합니다. 이번 저장은 실제 외부 공개를 시작합니다. 공개하면 안 되는 데이터가 없는지 확인한 뒤 진행합니다. 4편의 개발용 4101은 연결하지 않습니다.

Tunnel 실행하기

  1. Cloudflare 대시보드에서 Networking → Tunnels로 이동해 새 Tunnel을 만듭니다. 이전 화면에서는 Zero Trust의 Networks → Tunnels로 표시될 수 있습니다. 없으면 대시보드 검색에서 Tunnels를 찾습니다.
  2. 이름을 mini-workshop-public처럼 정하고 커넥터 설치 단계에서 Docker 방식을 확인합니다.
  3. 표시된 실행 명령의 Tunnel 토큰만 .env의 CLOUDFLARE_TUNNEL_TOKEN 값으로 저장합니다. 토큰이 포함된 전체 명령이나 파일을 글·스크린샷·GitHub에 올리지 않습니다.
  4. 같은 .env의 SITE_URL과 AUTH_URL을 본인 대표 HTTPS 주소로 바꿉니다. PUBLIC_INDEXING=false는 아직 유지합니다.
  5. 프로젝트 터미널에서 실행합니다.
docker compose -f compose.yaml -f compose.tunnel.yaml up -d --build
docker compose -f compose.yaml -f compose.tunnel.yaml ps

공개 경로 저장하기

Tunnel의 Routes에서 Add route → Published application을 선택합니다. 이전 UI에서는 Public Hostname 항목일 수 있습니다. 비공개 네트워크용 CIDR 경로와 혼동하지 않습니다.

| 입력 항목 | 넣을 값 | | --- | --- | | Domain | 본인 도메인 | | Subdomain | 대표 루트 주소라면 비움 | | Service URL | http://web:3000 |

서비스 입력이 유형과 주소로 나뉘면 유형은 HTTP, 주소는 web:3000입니다. 같은 Compose 네트워크의 web 서비스에 연결하므로 호스트 포트 4100이 아니라 컨테이너 포트 3000을 사용합니다. 저장 후 Tunnel 연결 상태와 생성된 DNS 레코드를 확인합니다.

자주 막히는 지점

왜 localhost:4100이 아닌가요? 이 예제는 cloudflared도 컨테이너입니다. 그 안의 localhost는 앱 컨테이너가 아니라 cloudflared 자신입니다. 같은 네트워크의 서비스 이름 web을 씁니다.

Tunnel은 정상인데 502가 나와요. 앱의 실행 상태와 web:3000을 먼저 확인합니다. DNS 캐시만 지우는 것으로 해결되지 않습니다.

같은 이름의 DNS 레코드가 있다고 해요. 신규 사이트의 동일 호스트 A/AAAA/CNAME 충돌을 확인합니다. 메일이나 다른 서비스 레코드를 통째로 지우지 않습니다.

앱을 다시 빌드할 때 Tunnel도 연결해야 하나요? 이 공개 환경의 관리 명령에는 두 Compose 파일을 함께 사용합니다. 개발 명령과 섞지 않습니다.

완료 기준과 검증

다른 네트워크에서 본인 도메인으로 첫 화면과 글 상세가 열려야 완료입니다. 예제의 앱·Docker 네트워크 구성은 검증했지만, 가상 도메인의 실제 Tunnel 공개는 수행하지 않았습니다. 토큰·실제 도메인 설정은 독자가 확인합니다.

공식 자료 확인: 2026-11-15. Tunnel 설정 공식 문서(영문), 공개 경로 공식 문서(영문).


6편: Cloudflare 네임서버 연결 · 8편: HTTPS와 www 정리