도커와 CI/CD — 자동으로 빌드하고 배포하기
처음 도커를 쓸 땐 로컬 환경에서 “이미지를 빌드해서 컨테이너를 실행하는 것”만으로도 충분했습니다.
하지만 서비스가 커지고 팀 단위로 협업하게 되면,
누가 어떤 코드를 배포했는지 관리가 필요해집니다.
수동으로 docker build, docker push, docker pull을 반복하다 보면
인간이 가장 많이 실수하는 부분 — 버전 관리와 환경 일관성 — 에서 문제가 터지죠.
그래서 등장하는 게 CI/CD 파이프라인에 도커를 통합하는 방식입니다.
내가 처음 자동 배포를 시도했을 때
예전에 사이드 프로젝트를 EC2 위에서 운영할 때였습니다.
깃허브에 커밋하면 서버에 반영되도록 만들고 싶었죠.
처음엔 직접 스크립트를 짰습니다.
git pull origin main
docker build -t myapp .
docker stop myapp
docker rm myapp
docker run -d -p 80:80 myapp
이걸 deploy.sh로 만들어 놓고, 서버에서 직접 실행했습니다.
그런데 어느 순간,
배포할 때마다 사람이 들어가서 명령을 치는 게 너무 번거로웠습니다.
그때 GitHub Actions를 처음 도입했습니다.
GitHub Actions로 도커 빌드 자동화하기
GitHub Actions를 사용하면,
코드가 푸시될 때 자동으로 도커 이미지를 빌드하고
Docker Hub나 GHCR에 푸시하도록 설정할 수 있습니다.
.github/workflows/docker-deploy.yml 파일을 생성하고 아래처럼 작성합니다.
name: CI/CD with Docker
on:
push:
branches:
- main
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and Push Docker Image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: mydockerid/myapp:latest
이 파일을 커밋하면,
GitHub가 자동으로 코드를 받아서 이미지를 빌드하고
Docker Hub에 푸시합니다.
이걸 처음 성공시켰을 때 느꼈던 쾌감은 아직도 기억납니다.
서버에 로그인할 필요도 없이,
커밋 한 번으로 배포가 끝나니까요.
서버에서 자동으로 새 이미지 받아오기
다음 단계는 서버 쪽 자동화입니다.
Docker Hub에 새 이미지가 올라가면,
서버에서 자동으로 docker pull을 실행하도록 구성하는 거죠.
가장 간단한 방법은 GitHub Actions에 SSH 배포 단계를 추가하는 겁니다.
- name: Deploy to EC2
uses: appleboy/ssh-action@v1.1.0
with:
host: ${{ secrets.EC2_HOST }}
username: ubuntu
key: ${{ secrets.EC2_SSH_KEY }}
script: |
docker pull mydockerid/myapp:latest
docker stop myapp || true
docker rm myapp || true
docker run -d -p 80:80 mydockerid/myapp:latest
이렇게 하면 깃허브에 푸시 → 자동 빌드 → 자동 배포까지 전부 연결됩니다.
이게 바로 완전한 CI/CD 파이프라인의 기본 형태입니다.
Jenkins나 GitLab CI에서도 동일한 원리

회사에서 Jenkins나 GitLab CI를 쓰고 있다면 원리는 같습니다.
빌드 → 테스트 → 이미지 푸시 → 서버 배포 순서만 유지하면 됩니다.
예를 들어 Jenkins에서는 아래처럼 파이프라인을 구성합니다.
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'docker build -t myapp:latest .'
}
}
stage('Push') {
steps {
sh 'docker push mydockerid/myapp:latest'
}
}
stage('Deploy') {
steps {
sh '''
ssh ubuntu@server '
docker pull mydockerid/myapp:latest &&
docker stop myapp || true &&
docker rm myapp || true &&
docker run -d -p 80:80 mydockerid/myapp:latest
'
'''
}
}
}
}
도커 기반 배포의 좋은 점은,
CI/CD 툴이 바뀌어도 “빌드-푸시-실행” 패턴은 그대로 유지된다는 점입니다.
자동 배포를 도입하고 달라진 점
예전엔 개발자들이 “배포 담당자”를 기다렸습니다.
커밋하고 나면 “언제 배포돼요?”가 일상이었죠.
이제는 단 한 줄의 커밋 메시지만 보면 됩니다.
“✅ Deploy success (via Actions)”
CI/CD 시스템이 배포를 대신해주니까요.
덕분에 버그 수정, 핫픽스 반영 속도가 3배 이상 빨라졌고,
팀 내에서 배포 스트레스가 거의 사라졌습니다.
CI/CD 구축 시 기억해야 할 팁
- latest 태그만 쓰지 말고, 커밋 SHA나 버전을 같이 써라.
- Secrets는 절대 코드에 직접 쓰지 말고 GitHub Secrets, Jenkins Credentials로 관리하라.
- 실패 시 Slack이나 Discord 알림을 연동하면 배포 상태를 실시간으로 확인할 수 있다.
- 테스트가 통과된 코드만 배포하도록 자동 검증 단계를 꼭 추가하라.