목차
도커 세팅 전 간단히 알아보기
도커 이미지
도커 이미지는 컨테이너를 생성할 때 필요한 요소 이며, 가상 머신을 생성할 때 사용하는 iso 파일과 비슷한 개념이다. 이미지는 여러 개의 계층으로 된 바이너리 파일로 존재, 컨테이너를 생성하고 실행할 때 읽기 전용으로 사용된다.
도커 컨테이너
도커 컨테이너는 이미지로 컨테이너를 생성하면 해당 이미지의 목적에 맞는 파일이 들어 있는 파일 시스템과 격리된 시스템 자원 및 네트워크를 사용할 수 있는 독립된 공간이 생성되는것을 말한다. 생성된 컨테이너는 각기 독립된 파일시스템을 제공받으며 호스트와 분리돼 있으므로 특정 컨테이너에서 어떤 어플리케이션을 설치하거나 삭제해도 다른 컨테이너와 호스트는 변화가 없다.
도커 볼륨
도커 이미지로 컨테이너를 생성하면 이미지는 읽기 전용이 되어 컨테이너의 변경 사항만 별도로 저장해서 각 컨테이너의 정보를 보존한다. 즉 mysql 이미지를 통해서 컨테이너를 생성하고 데이터를 저장하는 경우 컨테이너 내부에 저장된다는 것이다. 이것은 치명적인 단점이다. mysql 컨테이너를 삭제하면 컨테이너 계층에 저정되어 있는 데이터베이스의 정보도 삭제된다는 점이다. 도커 컨테이너는 삭제와 생상이 매우 쉬워 삭제되는 경우 데이터를 복구 할 수 없게 된다. 이를 방지하기 위해서 컨테이너의 데이터를 영속적(Persistent) 데이터로 활용할 수 있는 방법으로 도커 볼륨을 활용한다.
스크립트 쉘 설정
우리는 서버에서 직접 명령어를 사용해서 일일히 해줄 수 있지만 비효율적이다.
따라서 불필요한 과정의 중복을 줄이기 위해 다음과 같이 작성할 수 있다.
간단히 설명하면 다음과 같다.
1. 먼저 내가 설정한 경로로 이동시킨다.
2. 최신 코드를 pull 받는다.
3. 도커 컨테이너를 재시작한다.
이때 docker-compose down을 통해 실행중인 컨테이너를 중단시켜야 하는 것이 아닌가 할 수 있지만
docker-compose down은 볼륨을 초기화 시켜버린다.
docker-compose up은 빠르게 재시작 역할을 한다.
#!/bin/sh
PROJECT_PATH="/home/ubuntu"
PROJECT_NAME="backend"
LOG_FILE="/home/ubuntu/deploy-$(date +%F-%H%M%S).log"
cd "$PROJECT_PATH/$PROJECT_NAME" || {
echo "❌ 디렉토리 이동 실패: $PROJECT_PATH/$PROJECT_NAME" | tee -a "$LOG_FILE"
exit 1
}
echo "🐳 git pull 실행..." | tee -a "$LOG_FILE"
git pull origin main 2>&1 | tee -a "$LOG_FILE"
echo "🐳 docker-compose up --build -d 실행..." | tee -a "$LOG_FILE"
docker-compose up --build -d 2>&1 | tee -a "$LOG_FILE"
echo "✅ 배포 완료!" | tee -a "$LOG_FILE"
echo "로그 확인: $LOG_FILE"
앞으로의 ci cd작업 플로우에서 최종적으로 실행될 명령어들의 모임이라고 생각하면 편하다.
미리 서버 cmd에서 vi를 통해 만들어 주도록 하자
도커 컨테이너 세팅 파일
mysql + expressJS
docker-compose.yml
version: "3.8"
services:
mysql:
image: mysql:latest
container_name: mysql-container
ports:
- "3305:3306"
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${DB_NAME}
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 5s
timeout: 3s
retries: 5
backend:
build: .
container_name: backend-container
ports:
- "3000:3000"
depends_on:
mysql:
condition: service_healthy
env_file:
- .env
실행 순서 결정 파일
mysql 이 실행되고 서버가 실행되어야 하기 때문에 이 파일이 필요하다.
docker-entrypoint.sh
#!/bin/sh
echo "⏳ DB 서버가 준비될 때까지 대기합니다..."
dockerize -wait tcp://mysql:3306 -timeout 20s
echo "✅ DB 서버 감지 완료, Node 서버 시작!"
node dist/index.js
도커실행 파일
이 Dockerfile은 Node.js 기반 백엔드 프로젝트를 컨테이너화하기 위한 설정을 정의합니다.
DockerFile
# backend/Dockerfile
FROM node:18
WORKDIR /app
COPY package*.json ./
RUN yarn install
COPY . .
RUN yarn build
# ✅ dockerize 설치
ADD https://github.com/jwilder/dockerize/releases/download/v0.6.1/dockerize-linux-amd64-v0.6.1.tar.gz /tmp/
RUN tar -C /usr/local/bin -xzvf /tmp/dockerize-linux-amd64-v0.6.1.tar.gz
# ✅ 엔트리포인트 스크립트 복사
COPY docker-entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
EXPOSE 3000
# ✅ 실행 명령 변경
ENTRYPOINT ["docker-entrypoint.sh"]
cicd 파일 작성 (깃허브 액션)
ci.yml
이 파일은 PR 시점에서만 실행되며 코드가 문제없이 빌드되고 테스트되는지 검증한다.
# .github/workflows/ci.yml
name: CI - Build & Test
on:
pull_request:
branches: [main]
jobs:
ci:
runs-on: ubuntu-latest
steps:
- name: Checkout source
uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: yarn install
- name: Type check
run: yarn tsc --noEmit
- name: Lint
run: yarn lint
- name: Build
run: yarn build
cd.yml
이 파일은 오직 main 브랜치로의 머지 완료 시점에만 실행되어, 실서버 배포만 담당합니다.
# .github/workflows/deploy.yml
name: CD - Deploy to EC2
on:
pull_request:
types: [closed]
branches: [main]
jobs:
deploy:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- name: Connect to EC2 and run script
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.EC2_HOST }}
username: ubuntu
key: ${{ secrets.EC2_KEY }}
script: |
echo "🔄 .env 구성 중..."
cat <<EOF > /home/ubuntu/backend/.env
KAKAO_REST_API_KEY=${{ secrets.KAKAO_REST_API_KEY }}
MYSQL_ROOT_PASSWORD=${{ secrets.MYSQL_ROOT_PASSWORD }}
KAKAO_REDIRECT_URI=http://localhost:5173/auth/kakao/callback
GOOGLE_API_KEY=${{ secrets.GOOGLE_API_KEY }}
JWT_SECRET=${{ secrets.JWT_SECRET }}
REL_DB_HOST=mysql
REL_DB_PORT=3306
ENV=REL
DB_PASSWORD=${{ secrets.DB_PASSWORD }}
DB_NAME=${{ secrets.DB_NAME }}
DB_USER=${{ secrets.DB_USER }}
EOF
echo "✅ .env 작성 완료"
echo "🚀 bapo.sh 실행 시작"
/home/ubuntu/growthon/bapo.sh
이때 env 파일은 깃허브에 올라가지 않도록 설정했기 때문에 깃허브 액션의 시크릿 키 설정을 해주었다.
그래서 cicd가 진행될때 env 파일을 서버 코드에서 작성이 이루어지게 만들었다.

++개발 환경 나누기
개발 환경에서는 mysql 컨테이너만 도커에 띄우고 서버환경을 실시간으토 테스트하고 싶을 수 있다.
docker-compose.dev.yml
아래와 같이 개발환경용 도커 컨테이너 세팅 파일을 만든다.
version: "3.8"
services:
mysql:
image: mysql:latest
container_name: mysql-container
ports:
- "3305:3306"
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${DB_NAME}
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 5s
timeout: 3s
retries: 5
package.json
그 후 따로 명령어를 설정해 준다.
"scripts": {
"build": "tsc",
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "nodemon",
"start": "node -r tsconfig-paths/register dist/index.js",
"db:up": "docker-compose -f docker-compose.dev.yml up -d",
"db:down": "docker-compose -f docker-compose.dev.yml down"
},
'backend' 카테고리의 다른 글
| 서버 궁금증 해결기 (0) | 2025.07.09 |
|---|---|
| 우당탕탕 aws서버 ssl 인증하기 feat: certbot (2) | 2025.05.21 |
| [MySql] Docker setting 해보자 (1) | 2025.05.14 |