Backend/강의

[🐋 Docker + CI/CD] 3-1. Dockerfile 과 Docker Compose

가지코딩 2025. 7. 2. 22:46

🐋 목차

  1. Dockerfile
  2. Docker Compose
  3. Docker Compose 실습

🩵 학습 목표

  • Dockerfile 을 활용하여 나만의 이미지를 만들 수 있습니다.
  • Docker Compose 를 활용하여 여러 개의 컨테이너를 관리할 수 있습니다.

1. Dockerfile

Dockerfile

  • Docker 이미지 생성을 위한 빌드 명세 파일
  • 텍스트 형식의 스크립트 파일로, 도커가 이미지를 생성할 때 따라야 하는 지시어(instruction)들을 포함한다.
  • Dockerfile은 사용자가 정의한 명령어들을 기반으로 새로운 도커 이미지를 생성하는 데 사용된다.
  • 해당 명령어들은 계층(layer) 단위로 실행되며, 각 계층은 캐시될 수 있다.

 

주요 특징

  • 비결정적 상태 방지: 명령어 순서와 내용을 명확하게 기술하여 빌드 과정의 재현성을 보장한다.
  • Immutable Image 정의: 컨테이너는 Dockerfile로 정의된 이미지로부터 동일한 상태로 실행 가능하다.
  • Layered Filesystem: 각 명령어는 파일시스템 레이어를 생성하며, 변경된 레이어만 캐시 무효화된다.

 

주요 명령어 (Instruction)

명령어 설명
FROM 베이스 이미지 지정. 모든 Dockerfile은 이 명령어로 시작해야 함.
RUN 빌드 시 실행할 명령어. 예: 패키지 설치, 빌드 작업 등
CMD 컨테이너가 실행될 때 기본으로 실행될 명령 지정.
COPY 호스트 시스템의 파일을 이미지에 복사.
ADD COPY와 유사하나 URL 및 압축 해제 지원.
WORKDIR 이후 명령어가 실행될 작업 디렉토리 설정.
ENV 환경 변수 설정.
EXPOSE 컨테이너에서 열 포트를 명시. 네트워크 연결 용도로 사용.
ENTRYPOINT 실행 파일 및 인자를 고정적으로 설정할 때 사용.
ARG 빌드 시점에 사용할 변수 정의. ENV와 달리 런타임에서는 무효.

 

 

기본 구조 예시

# 1. 베이스 이미지 선택 (예: node.js 환경)
FROM node:18

# 2. 작업 디렉토리 설정
WORKDIR /app

# 3. 로컬 파일을 이미지에 복사
COPY package.json ./
COPY . .

# 4. 의존성 설치
RUN npm install

# 5. 앱 실행
CMD ["npm", "start"]

 

 

사용 흐름

  1. Dockerfile 작성
  2. docker build 명령어로 이미지 생성
  3. 생성된 이미지를 바탕으로 컨테이너 실행

 

Dockerfile 예제

더보기

FastAPI 앱을 실행하는 예제

FROM python:3.11

RUN pip install pipenv

WORKDIR /app

ADD . /app/

RUN pipenv --python 3.11
RUN pipenv run pip install poetry
RUN pipenv sync
RUN pipenv run pip install certifi

ARG STAGE

RUN sh -c 'echo "STAGE=$STAGE" > .env'
RUN sh -c 'echo "PYTHONPATH=." >> .env'
RUN chmod +x ./scripts/run.sh
RUN chmod +x ./scripts/run-worker.sh

CMD ["./scripts/run.sh"]

 

 

 nginx 이미지를 생성하는 예제

  • 실제로는 nginx:latest 이미지를 사용하면 되지만, 예제를 위해 만들어 보았다.
# Dockerfile
FROM ubuntu:22.04
MAINTAINER your-name <your-email@example.com>
LABEL purpose=Web Server

# nginx 패키지 설치
RUN apt-get update && apt-get install -y nginx

# nginx 설정 파일 복사
COPY nginx.conf /etc/nginx/nginx.conf

# Nginx 실행
CMD ["nginx", "-g", "daemon off;"]
# nginx.conf
user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    gzip  on;
    gzip_disable "msie6";

    include /etc/nginx/conf.d/*.conf;
}

2. Docker Compose

Docker Compose

  • 여러 개의 Docker 컨테이너를 정의하고 동시에 실행하기 위한 도구
  • 애플리케이션을 구성하는 여러 서비스(예: 웹 서버, DB 등)를 하나의 설정 파일(docker-compose.yml)에 선언하고,
    명령어 하나로 일괄적으로 빌드, 생성, 네트워크 연결, 시작할 수 있게 해준다.

 

핵심 역할

  • 멀티 컨테이너 환경 구성
  • 컨테이너 간의 의존성 정의 및 관리
  • 통합된 빌드/실행/종료 관리
  • 프로젝트별 고립된 네트워크 자동 구성

 

구성 요소

  • docker-compose.yml 파일
    • services: 컨테이너 단위 구성
    • web: 사용자 정의 서비스 이름
    • depends_on: 실행 순서 정의 (의존 관계)
    • environment: 환경 변수 전달
version: '3.8'
services:
  web:
    build: .
    ports:
      - "8080:8080"
    depends_on:
      - db
  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: example

 

 

 

명령어 인터페이스

명령어 설명
docker-compose up 정의된 모든 서비스를 빌드 및 실행
docker-compose down 실행 중인 모든 서비스 중지 및 네트워크 제거
docker-compose build 이미지 빌드만 실행
docker-compose logs 서비스별 로그 출력
docker-compose ps 실행 중인 서비스 목록 확인

 

 

Compose가 내부적으로 하는 일

  1. docker network를 생성하여 서비스 간 통신 가능하게 함
  2. 각 서비스에 대해 docker build 또는 docker run 수행
  3. 컨테이너 이름을 고유하게 지정 (프로젝트_서비스_순번)
  4. depends_on, restart, volumes, environment 등의 설정 반영

 

Docker Compose 예시

더보기

Spring + MySQL 구성 예시

  • app은 로컬에서 빌드되는 Spring 애플리케이션
  • mysql은 MySQL 공식 이미지 사용
  • app은 mysql 서비스에 연결 (mysql은 내부 DNS 호스트명)
version: '3.8'
services:
  app:
    build: .
    ports:
      - "8080:8080"
    depends_on:
      - mysql
    environment:
      SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/testdb

  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: testdb
    ports:
      - "3306:3306"

 

 

fastapi app

# Dockerfile
FROM python:3.10

RUN pip install pipenv

WORKDIR /app

ADD . /app/

RUN pipenv --python 3.10
RUN pipenv run pip install poetry
RUN pipenv sync
RUN pipenv run pip install certifi


ARG STAGE

RUN sh -c 'echo "STAGE=$STAGE" > .env'
RUN sh -c 'echo "PYTHONPATH=." >> .env'
# ENV PYTHONPATH=/app
RUN chmod +x ./scripts/run.sh
RUN chmod +x ./scripts/run-worker.sh

# ENV PYTHONPATH=/app
CMD ["./scripts/run.sh"]
# docker-compoe.yaml
version: "3"
services:
  channel-api:
    image: xxxx.dkr.ecr.ap-northeast-2.amazonaws.com/reaction-channel:${AWS_ENV_STAGE:-dev}-${TAG:-latest}
    build:
      context: .
      dockerfile: dockerfile
      args:
        STAGE: ${STAGE:-develop}
    ports:
      - "8000:8000"
    environment:
      - NEW_RELIC_CONFIG_FILE=newrelic.ini
      - NEW_RELIC_ENVIRONMENT=ecs-${STAGE:-develop}
    logging:
      driver: awslogs
      options:
        awslogs-stream-prefix: channel
        awslogs-group: /ecs/reaction/${AWS_ENV_STAGE:-dev}/channel-api
        awslogs-region: ap-northeast-2

  reverseproxy:
    image: xxxxx.dkr.ecr.ap-northeast-2.amazonaws.com/reverseproxy:prod-channel-latest
    ports:
    - "80:80"
    - "81:81"
    logging:
      driver: awslogs
      options:
        awslogs-stream-prefix: reverseproxy
        awslogs-group: /ecs/reaction/${AWS_ENV_STAGE:-dev}/reverseproxy
        awslogs-region: ap-northeast-2

3. Docker Compose 실습

https://github.com/gajicoding/docker-compose-sample

 

GitHub - gajicoding/docker-compose-sample

Contribute to gajicoding/docker-compose-sample development by creating an account on GitHub.

github.com

 

docker-compose 로 실행

cd ~/docker-compose-sample
docker-compose up -d
docker-compose logs -f

 

redis 연결 테스트