[Docker] 예제
2024. 12. 9. 19:45ㆍTools/Docker
3번의 프로젝트를 진행하면서 추후 참고할 만한 부분만 가져왔습니다.
1. 디렉터리 구조
- frontend, backend 소스코드에 이미지 빌드를 위한 Dockerfile을 생성.
- https 인증서 발급을 위한
cert-compose.yml
과nginx.conf
. - db를 위한
db-compose.yml
생성. - application 실행을 위한
app-compose.yml
과 reverse proxy를 위한 nginx 설정 파일들 추가.
2. Dockerfile 예시
가. frontend (react)
# 5173 port를 사용하는 React를 정적으로 빌드하다음 Nginx를 이용해 배포한다.
# nginx 이미지를 사용합니다. 뒤에 tag가 없으면 latest 를 사용합니다.
FROM nginx:1.26.1
# root 에 app 폴더를 생성
RUN mkdir /app
# work dir 고정
WORKDIR /app
# work dir 에 build 폴더 생성 /app/build
RUN mkdir /build
# host pc의 현재경로의 dist 폴더를 workdir 의 build 폴더로 복사
ADD ./dist ./build
# nginx 의 default.conf 를 삭제
RUN rm /etc/nginx/conf.d₩/default.conf
# 80 포트 오픈
EXPOSE 80
# 443 포트 오픈
EXPOSE 443
# container 실행 시 자동으로 실행할 command. nginx 시작함
CMD ["nginx", "-g", "daemon off;"]
- React 빌드 후 생성된 정적 파일을 nginx에서 서빙하도록 구성.
나. backend (java)
FROM openjdk:17-oracle
EXPOSE 8080
ARG JAR_FILE=build/libs/*.jar
COPY ${JAR_FILE} app.jar
ENV TZ=Asia/Seoul
ENTRYPOINT ["java","-jar","/app.jar"]
- Spring boot 빌드 후 생성된 jar 파일을 실행하도록 구성.
다. backend (python)
FROM ubuntu:22.04
# Set Environment Variables
ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Asia/Seoul
# Install dependencies
RUN apt-get update && \
apt-get install -y --no-install-recommends \
python3.11 \
python3-pip && \
apt-get clean && rm -rf /var/lib/apt/lists/*
# update pip to 24.2
RUN python3 -m pip install --upgrade pip==24.2
# Set default Python and pip commands
RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.11 1 && \
update-alternatives --install /usr/bin/pip pip /usr/bin/pip3 1
# UTF-8 환경 설정
ENV PYTHONENCODING=utf-8
# Set a working directory
WORKDIR /app
# Make src directory and copy the source code
RUN mkdir src
# Copy the current directory contents into the container at /app
COPY requirements.txt /app/
# Install any needed packages specified in requirements.txt
RUN pip install --no-cache-dir -r requirements.txt
# Install dependencies for Firefox
RUN apt-get update && apt-get install -y \
wget \
bzip2 \
libgtk-3-0 \
libdbus-glib-1-2 \
libxt6 \
libx11-xcb1 \
libpci3 \
libasound2 \
libxcomposite1 \
libxdamage1 \
libxfixes3 \
libcairo2 \
libpango-1.0-0 \
libpangocairo-1.0-0 \
libxtst6 \
libgtk2.0-0 \
&& rm -rf /var/lib/apt/lists/*
# Install Firefox
# RUN apt-get update && apt-get install -y firefox==132.0.2
WORKDIR /tmp
RUN wget https://download-installer.cdn.mozilla.net/pub/firefox/releases/132.0.2/linux-x86_64/en-US/firefox-132.0.2.tar.bz2
RUN tar xjf firefox-132.0.2.tar.bz2 && mv firefox /opt/firefox && ln -s /opt/firefox/firefox /usr/local/bin/firefox
# Install geckodriver
RUN wget https://github.com/mozilla/geckodriver/releases/download/v0.35.0/geckodriver-v0.35.0-linux64.tar.gz
RUN tar -xvzf geckodriver-v0.35.0-linux64.tar.gz
RUN chmod +x geckodriver && mv geckodriver /usr/local/bin/
# Remove unnecessary files
RUN rm -rf /tmp/*
# Copy source code
WORKDIR /app
COPY src /app/src
CMD ["python3", "/app/src/main.py"]
- 실행에 필요한 dependency 설치 후 python 실행.
3. docker-compose.yml 예시
가. certbot
services:
nginx:
image: nginx:latest
container_name: nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./data/nginx:/etc/nginx/conf.d
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
certbot:
image: certbot/certbot
command: certonly --webroot --webroot-path=/var/www/certbot --email fkaus4598@naver.com --agree-tos --no-eff-email -d mobipay.kr -d merchant.mobipay.kr
volumes:
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
depends_on:
- nginx
- 구매한 도메인으로 https 인증서 발급.
나. db (mysql)
services:
mobi-db:
image: mysql:8.4.1
volumes:
- mobi-db-data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: ${MOBI_ROOT_PASSWORD}
MYSQL_DATABASE: ${MOBI_DATABASE}
MYSQL_USER: ${MOBI_USER}
MYSQL_PASSWORD: ${MOBI_PASSWORD}
TZ: Asia/Soeul
LANG: C.UTF-8
expose:
- 3306
networks:
- mobi-network
container_name: mobi-db
mer-db:
image: mysql:8.4.1
volumes:
- mer-db-data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: ${MER_ROOT_PASSWORD}
MYSQL_DATABASE: ${MER_DATABASE}
MYSQL_USER: ${MER_USER}
MYSQL_PASSWORD: ${MER_PASSWORD}
TZ: Asia/Soeul
LANG: C.UTF-8
expose:
- 3306
networks:
- mer-network
container_name: mer-db
volumes:
mobi-db-data:
mer-db-data:
networks:
mobi-network:
name: mobi-network
driver: bridge
mer-network:
name: mer-network
driver: bridge
- mysql 컨테이너와 네트워크를 생성한다.
다. app
services:
reverse-proxy:
image: ramen4598/mobipay_nginx:latest
depends_on:
- mobi-backend
- mer-backend
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/:/etc/nginx/
- ../cert/data/certbot/conf:/etc/letsencrypt
- ../cert/data/certbot/www:/var/www/certbot
networks:
- reverse-proxy
restart: always
container_name: reverse-proxy
mobi-backend:
image: ramen4598/mobipay_mobipay:latest
env_file:
- .env
environment:
MYSQL_HOST: mobi-db
MYSQL_PORT: 3306
MYSQL_DB: ${MOBI_DB}
MYSQL_USER: ${MOBI_USER}
MYSQL_PASSWORD: ${MOBI_PASSWORD}
TZ: Asia/Seoul
expose:
- 8080
networks:
- reverse-proxy
- mobi-network
restart: always
container_name: mobi-backend
mer-backend:
image: ramen4598/mobipay_merchant:latest
env_file:
- .env
environment:
MYSQL_HOST: mer-db
MYSQL_PORT: 3306
MYSQL_DB: ${MER_DB}
MYSQL_USER: ${MER_USER}
MYSQL_PASSWORD: ${MER_PASSWORD}
TZ: Asia/Seoul
expose:
- 8080
networks:
- reverse-proxy
- mer-network
restart: always
container_name: mer-backend
networks:
reverse-proxy:
driver: bridge
mobi-network:
external: true
name: mobi-network
mer-network:
external: true
name: mer-network
- nginx reverse proxy를 생성.
- backend 생성.
- db 연결.
라. 기타
services:
db:
image: mysql:8.4.1
volumes:
- 'mysql_data:/var/lib/mysql'
profiles: ["dev", "prod"]
restart: always
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DB}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
TZ: Asia/Seoul
LANG: C.UTF-8
healthcheck:
test: [ "CMD", "mysqladmin" ,"ping", "-h", "localhost" ]
timeout: 20s
retries: 10
expose:
- "3306"
networks:
- moducha
container_name: moducha_db
backend-dev:
depends_on:
db:
condition: service_healthy
profiles:
- dev
build:
context: ./backend
dockerfile: Dockerfile
image: moducha_backend
env_file: '.env'
restart: 'always'
expose:
- "8080"
...
1) health check
healthcheck:
test: [ "CMD", "mysqladmin" ,"ping", "-h", "localhost" ]
timeout: 20s
retries: 10
MySQL 컨테이너의 상태를 체크하는 healthcheck 설정이다.
mysqladmin ping 명령어로 데이터베이스 연결을 확인하며, 20초 타임아웃에 최대 10번 재시도한다.
depends_on:
db:
condition: service_healthy
이 설정은 다른 서비스가 MySQL 컨테이너에 의존성이 있을 때 사용된다.
MySQL이 완전히 준비된 상태(healthy)일 때만 의존하는 서비스가 시작되도록 보장한다.
2) expose & port
expose:
- "3306"
설정 | 설명 | 접근 범위 |
expose | 같은 Docker 네트워크 내 컨테이너 간 통신을 위한 포트 노출 | 같은 네트워크의 컨테이너만 접근 가능 |
ports | 호스트와 컨테이너 간 포트 매핑 | 호스트 시스템 및 외부에서 접근 가능 |
보안을 위해서 외부에 노출할 이유가 없다면 expose
를 사용하자.
3) env_file
env_file: '.env'
환경 변수를 별도의 .env
파일에서 읽어오도록 설정합니다.
민감한 정보를 compose 파일과 분리하여 관리할 수 있게 한다.
4) build
build:
context: ./backend
dockerfile: Dockerfile
docker compose
실행 시 Docker 이미지를 빌드하는 설정.
context
: 도커 빌드가 실행될 디렉터리 경로를 지정.dockerfile
: 사용할 Dockerfile의 이름을 지정. 기본값은Dockerfile
이다.
4. env
프레임워크 | 환경변수 주입 시점 | 주입 방법 |
Java Spring | 실행 시점 | docker-compose의 environment 설정 |
React | 빌드 시점 | 이미지 빌드 시 포함 |
Python | 실행 시점 | docker-compose의 environment 설정 |
'Tools > Docker' 카테고리의 다른 글
[Docker] MySQL 설치 (0) | 2023.03.10 |
---|---|
[Docker] Multi-architecture build (0) | 2023.03.07 |
[Docker] Github와의 연동 (0) | 2023.02.28 |
[Docker] 연습하기 (2) | 2023.02.27 |
[Docker] Compose (0) | 2023.02.27 |