Docker 개념과 설치부터 Dockerfile 작성, Docker Compose로 멀티 컨테이너 구성, GitHub Actions 워크플로 작성, 자동 빌드와 테스트, Docker Hub 푸시, 서버 자동 배포까지 -- 실무에서 바로 복사해 쓸 수 있는 설정 파일 위주로 정리했다.
왜 Docker가 필요한가
개발 환경에서는 잘 되던 코드가 서버에서 안 돌아가는 경험, 한 번쯤 있을 것이다. "내 컴퓨터에서는 되는데" -- Docker는 이 문제를 근본적으로 해결한다.
01
환경 일관성 보장
개발 PC, 테스트 서버, 프로덕션 서버 어디서나 동일한 환경에서 실행된다.
02
빠른 배포와 롤백
이미지 빌드 후 어디서든 동일하게 실행된다. 문제가 생겨도 이전 이미지 태그로 즉시 롤백 가능하다.
03
격리된 실행 환경
각 서비스가 독립된 컨테이너에서 실행되어 의존성 충돌이 없다. Node.js 18과 20을 동시에 운영할 수 있다.
04
CI/CD 파이프라인의 기반
GitHub Actions와 결합하면 코드 푸시에서 자동 테스트, 자동 배포까지 완전히 자동화된다.
Docker 핵심 개념 정리
| 용어 | 설명 | 비유 |
| Image | 컨테이너 실행에 필요한 모든 파일 묶음 (읽기 전용) | 요리 레시피 |
| Container | 이미지로 실행 중인 인스턴스 (여러 개 가능) | 레시피로 만든 요리 |
| Dockerfile | 이미지 빌드 지침서 | 레시피 작성 |
| Docker Hub | 이미지 저장/공유 레지스트리 | 레시피 책 도서관 |
| Compose | 여러 컨테이너를 한 번에 관리하는 도구 | 풀코스 요리 관리 |
자주 쓰는 Docker 명령어
bash
# 이미지 관련
docker build -t myapp:1.0 . # 이미지 빌드
docker images # 이미지 목록
docker pull node:20-alpine # 이미지 다운로드
# 컨테이너 관련
docker run -d -p 3000:3000 myapp:1.0 # 백그라운드 실행 + 포트 매핑
docker ps # 실행 중 컨테이너 목록
docker logs -f container_id # 로그 실시간 출력
docker exec -it container_id bash # 컨테이너 내부 접속
Dockerfile 작성 실전
Dockerfile은 이미지를 만드는 설계도다. 레이어(layer) 구조로 되어 있어 변경된 부분만 다시 빌드하므로, 순서 설계가 빌드 성능을 좌우한다.
Node.js 앱 Dockerfile (프로덕션 최적화)
dockerfile
# 1단계: 빌드 스테이지
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
# 2단계: 런타임 스테이지
FROM node:20-alpine AS runner
WORKDIR /app
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
COPY --from=builder --chown=appuser:appgroup /app/dist ./dist
COPY --from=builder --chown=appuser:appgroup /app/node_modules ./node_modules
COPY --from=builder --chown=appuser:appgroup /app/package.json ./
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s \
CMD wget -qO- http://localhost:3000/health || exit 1
CMD ["node", "dist/index.js"]
이미지 크기 최소화 팁
Alpine 기반 이미지 사용, 멀티 스테이지 빌드, .dockerignore 철저히 설정, RUN 명령어 체이닝으로 레이어 수 감소 (RUN cmd1 && cmd2 && cmd3)
Docker Compose -- 멀티 컨테이너 구성
실제 서비스는 앱 서버 + 데이터베이스 + 캐시 등 여러 컨테이너로 구성된다. Docker Compose는 이를 하나의 파일로 관리한다.
docker-compose.yml
version: '3.9'
services:
app:
build:
context: .
target: runner
image: myapp:latest
restart: unless-stopped
ports:
- "3000:3000"
depends_on:
db:
condition: service_healthy
networks:
- app-net
db:
image: postgres:16-alpine
restart: unless-stopped
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user -d mydb"]
interval: 10s
timeout: 5s
retries: 5
networks:
- app-net
cache:
image: redis:7-alpine
restart: unless-stopped
networks:
- app-net
volumes:
postgres-data:
networks:
app-net:
driver: bridge
GitHub Actions CI/CD 파이프라인
GitHub Actions는 코드 저장소와 완벽하게 통합된 CI/CD 플랫폼이다. main 브랜치에 Push하면 테스트, Docker 이미지 빌드, Docker Hub 푸시, 서버 배포까지 완전 자동화된다.
CD 워크플로 -- Docker 빌드와 배포
yaml -- .github/workflows/deploy.yml
name: CD - 빌드 & 배포
on:
push:
branches: [main]
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Docker Buildx 설정
uses: docker/setup-buildx-action@v3
- name: Docker Hub 로그인
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Docker 이미지 빌드 & 푸시
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ github.repository }}:latest
cache-from: type=gha
cache-to: type=gha,mode=max
deploy:
needs: build-and-push
runs-on: ubuntu-latest
steps:
- name: SSH로 서버 배포
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SERVER_SSH_KEY }}
script: |
cd /app
docker compose pull app
docker compose up -d --no-deps app
docker image prune -f
GitHub Secrets 필수 등록
DOCKERHUB_USERNAME, DOCKERHUB_TOKEN, SERVER_HOST, SERVER_USER, SERVER_SSH_KEY를 Settings > Secrets and variables > Actions에서 등록해야 한다.
자동 서버 배포 구성
서버에서 새 이미지를 자동으로 받아 무중단 배포하는 설정이다. Nginx 리버스 프록시와 조합하면 완전한 프로덕션 환경을 구성할 수 있다.
최적화와 실전 팁
빌드 시간 단축 -- 레이어 캐시 활용
핵심 원칙
자주 변경되는 파일일수록 Dockerfile의 아래쪽에 배치하자. Docker는 변경된 레이어 이하를 모두 다시 빌드한다.
GitHub Actions 실전 체크리스트
파이프라인 구성 체크리스트
PR 시 자동 테스트 (branch protection rules), 빌드 캐시 적용으로 빌드 시간 50~70% 단축, 멀티 아키텍처 빌드 (linux/amd64,arm64), 이미지 취약점 스캔 (trivy-action), 배포 후 슬랙/디스코드 알림 연동, 오래된 이미지 자동 정리 (docker image prune)
정리
- Dockerfile -- 멀티스테이지 빌드 + 레이어 캐시 전략으로 이미지 최소화
- .dockerignore -- node_modules, .env, .git 반드시 제외
- Docker Compose -- depends_on + healthcheck으로 서비스 시작 순서 보장
- CI (ci.yml) -- PR마다 린트/테스트 자동 실행
- CD (deploy.yml) -- main 푸시 시 이미지 빌드/푸시/서버 배포 자동화
- Secrets -- GitHub Secrets에 크레덴셜 등록, 코드에 절대 포함 금지
이 파이프라인을 구축하면 코드 작성과 배포를 완전 분리하여 개발에만 집중할 수 있다.