
이식성 : 특정 프로그램을 다른 곳으로 쉽게 옮겨서 설치 및 실행할 수 있는 특성
Docker를 사용하면 아래와 같은 장점이 있다.
컨테이너를 사용하여 각각의 프로그램을 분리된 환경에서 실행 및 관리할 수 있는 툴이다.
하나의 컴퓨터 환경 내에서 독립적인 컴퓨터 환경을 구성해서, 각 환경에 프로그램을 별도로 설치할 수 있게 만든 개념이다. 하나의 컴퓨터 환경 내에서 여러개의 미니 컴퓨터 환경을 구성할 수 있는 형태이다. 여기서 얘기하는 미니 컴퓨터를 보고 Docker에서는 컨테이너(Container)라고 부른다.
이미지(Image)는 프로그램을 실행하는 데 필요한 설치 과정, 설정, 버전 정보 등을 포함하고 있다. 즉, 프로그램을 실행하는 데 필요한 모든 것을 포함하고 있다.
2023년 7월부터 Docker Compose V1의 업데이트를 중단했다. 따라서 Docker Compose는 V2를 설치할 것을 권장한다. 혹시나 기존에 설치되어 있는 Docker Compose의 버전이 V1이라면 V2로 교체할 것을 권장한다.
docker pull nginx
docker image ls
docker run --name webserver -d -p 80:80 nginx
Nginx와 React를 묶어서 하나의 이미지로 만들 것이다.
server {
listen 80;
server_name [server ip];
location / {
root /usr/share/nginx/html; # 리액트 파일 경로
index index.html index.htm;
try_files $uri $uri/ /index.html; # 리액트의 SPA 라우팅을 위해 index.html로 요청 전달
# location 안에 넣어줘야함
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
}
location /static/ {
alias /usr/share/nginx/html/static/;
}
location /api/ {
proxy_pass http://spring-app:8080;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# CORS 헤더 설정
add_header 'Access-Control-Allow-Origin' '[server ip]';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, Cache-Control, X-Requested-With';
# Preflight 요청(OPTIONS)을 위한 응답
if ($request_method = OPTIONS) {
add_header 'Access-Control-Allow-Origin' '[server ip]';
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, Cache-Control, X-Requested-With';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Max-Age' 1728000; # Preflight 요청을 캐시하는 시간 (20일)
return 204; # No Content 응답
}
}
}
Docker 이미지를 만들기 위한 설정 파일이다.
#이미지 빌드
docker build .
#또는
docker build -t <image_name> .
를 실행하면 Docker는 지정된 디렉터리에 있는 Dockerfile을 읽고 그 안의 지침을 순차적으로 실행한다. 각 명령어는 최종 이미지에 레이어를 생성한다.
FROM openjdk:17-jdk-slim
WORKDIR /app
COPY build/libs/tmarket-0.0.1.jar app.jar
EXPOSE 8080
CMD ["java", "-jar", "app.jar", "--spring.profiles.active=prod"]
# Step 1: Build the React app
FROM node:16-alpine AS build
WORKDIR /app
# 소스 코드 복사
COPY . .
RUN npm install --legacy-peer-deps # 종속성 충돌 무시하고 설치
# 소스 코드 복사
RUN npm run build
# Step 2: Nginx로 서비스
FROM nginx:alpine
# 기본 nginx 설정 파일을 삭제한다. (custom 설정과 충돌 방지)
RUN rm /etc/nginx/conf.d/default.conf
# custom 설정파일을 컨테이너 내부로 복사한다.
COPY conf/conf.d/default.conf /etc/nginx/conf.d/default.conf
# nginx 가 동작하기 위해 필요한 파일들을 시스템으로 복사
COPY --from=build /app/build /usr/share/nginx/html
# 포트 노출
EXPOSE 80
EXPOSE 443
# Nginx 실행
CMD ["nginx", "-g", "daemon off;"]
FROM : 베이스 이미지 생성
FROM은 베이스 이미지를 생성하는 역할을 한다. Docker 컨테이너를 특정 초기 이미지를 기반으로 추가적인 셋팅을 할 수 있다. 여기서 얘기한 ‘특정 초기 이미지’가 곧 베이스 이미지이다.# 문법
FROM [이미지명]
FROM [이미지명]:[태그명]COPY : 파일 복사(이동)
COPY는 호스트 컴퓨터에 있는 파일을 복사해서 컨테이너로 전달한다.# 문법
COPY [호스트 컴퓨터에 있는 복사할 파일의 경로] [컨테이너에서 파일이 위치할 경로]
# 예시
COPY app.txt /app.txtRUN : 이미지를 생성하는 과정에서 사용할 명령문 실행
RUN은 이미지 생성 과정에서 명령어를 실행시켜야 할 때 사용한다.
# 문법
RUN [명령문]
# 예시
RUN npm install
도커 컴포즈 는 단일 서버에서 여러개의 컨테이너를 하나의 서비스로 정의해 컨테이너의 묶음으로 관리할 수 있는 작업 환경을 제공하는 관리 도구
여러 개의 컨테이너를 관리하는 데 용이
여러 개의 컨테이너로 이루어진 복잡한 애플리케이션을 한 번에 관리할 수 있게 해준다.
여러 컨테이너를 하나의 환경에서 실행하고 관리하는 데 도움이 된다.
복잡한 명령어로 실행시키던 걸 간소화 시킬 수 있음
이전에 MySQL 이미지를 컨테이너로 실행시킬 때 아래와 같은 명령어를 실행시켰다.
$ docker run -e MYSQL_ROOT_PASSWORD=password123 -p 3306:3306 -v /Users/jaeseong/Documents/Develop/docker-mysql/mysql_data:/var/lib/mysql -d mysql
Docker Compose를 사용하면 위와 같이 컨테이너를 실행시킬 때마다 복잡한 명령어를 입력하지 않아도 된다. 단순히 docker compose up 명령어만 실행시키면 된다.
⭐️ docker compose up -d : docker run 을 간단하게 실행해줌
services:
spring-app:
image: won1110218/tmarket-back:latest
ports:
- 8080:8080
container_name: spring-app
depends_on:
redis:
condition: service_healthy
mysql:
condition: service_healthy
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/tmarket
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: ********
networks:
- tmarket-network
nginx:
image: won1110218/tmarket-front:latest
ports:
- 80:80
- 443:443
restart: always
environment:
TZ: Asia/Seoul
container_name: nginx
depends_on:
- spring-app
volumes:
- /home/ubuntu:/home/ubuntu # 인증서 파일을 위한 Volume 추가
networks:
- tmarket-network
mysql:
image: mysql:latest
environment:
MYSQL_USER: admin
MySQL_PASSWORD: dmstnr0218
MYSQL_ROOT_PASSWORD: dmstnr0218
MYSQL_DATABASE: tmarket # MySQL 최초 실행 시 tmarket 라는 데이터베이스를 생성해준다.
container_name: mysql
volumes:
- ./mysql_data:/var/lib/mysql
ports:
- 3307:3306 # 호스트의 3307 포트를 컨테이너의 3306 포트에 매핑
healthcheck:
test: [ "CMD", "mysqladmin", "ping" ] # MySQL 이 healthy 한 지 판단할 수 있는 명령어
interval: 5s # 5초 간격으로 체크
retries: 10 # 10번까지 재시도
networks:
- tmarket-network
redis:
image: redis:latest
container_name: redis
ports:
- 6379:6379
healthcheck:
test: [ "CMD", "redis-cli", "ping" ]
interval: 5s
retries: 10
networks:
- tmarket-network
networks:
tmarket-network:
driver: bridge
services: my-web-server : Docekr Compose에서 하나의 컨테이너를 서비스(service)라고 부른다. 이 옵션은 서비스에 이름을 붙이는 기능이다.container_name: web-server : 컨테이너를 띄울 때 붙이는 별칭이다. CLI에서 --name web-server 역할과 동일하다.image: nginx : 컨테이너를 실행시킬 때 어떤 이미지를 사용할 지 정의하는 명령어이다. $ docker run [이미지명]와 동일한 역할이다.ports : 포트 매핑은 어떻게 할 지를 설정하는 옵션이다. CLI에서-p 80:80 역할과 동일하다.
docker compose up # 포그라운드에서 실행
docker compose up -d # 백그라운드에서 실행
# compose.yml에 정의된 컨테이너 중 실행 중인 컨테이너만 보여준다.
docker compose ps
# compose.yml에 정의된 모든 컨테이너를 보여준다.
docker compose ps -a
# compose.yml에 정의된 모든 컨테이너의 로그를 모아서 출력한다.
docker compose logs
docker compose up --build # 포그라운드에서 실행
docker compose up --build -d # 백그라운드에서 실행
참고 :
docker compose upvsdocker compose up --build
docker compose up: 이미지가 없을 때만 빌드해서 컨테이너를 실행시킨다. 이미지가 이미 존재하는 경우 이미지를 빌드하지 않고 컨테이너를 실행시킨다.docker compose up --build: 이미지가 있건 없건 무조건 빌드를 다시해서 컨테이너를 실행시킨다.
docker compose pull
compose.yml에서 정의된 이미지를 다운 받거나 업데이트 한다.docker compose down
location /api/notifications/subscribe {
proxy_pass http://spring-app:8080; # HTTP로 Spring 애플리케이션에 연결
proxy_http_version 1.1; # Use HTTP/1.1 for SSE
proxy_set_header Upgrade $http_upgrade; # For upgrading to websocket if needed
proxy_set_header Connection "keep-alive"; # Necessary for SSE
proxy_set_header Host $host; # Forward the original Host header
proxy_set_header X-Real-IP $remote_addr; # Forward the client IP address
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # Proxy forwarding headers
proxy_set_header X-Forwarded-Proto $scheme; # Protocol used by the client (http or https)
proxy_buffering off; # Disable buffering for SSE
}