Spring Boot 프로젝트 빌드
// 터미널에서 해당 프로젝트 위치로 이동
./gradlew build
// gradlew 는 윈도우용.
Vue 프로젝트 빌드
// 터미널에서 해당 프로젝트 위치로 이동
npm run build
필요한 API 별로 Dockerfile 작성
# 예시 1
FROM openjdk:17-jdk-slim
WORKDIR /app
ENTRYPOINT ["java", "-jar", "app.jar"]
# 예시 2
FROM nginx:stable
COPY ./nginx.conf /etc/nginx/nginx.conf
# 로컬 경로 Docker 컨테이너 내 리눅스 경로
CMD ["nginx", "-g", "daemon off;"]
# .conf 예시
events{}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
upstream was {
server backend:8080;
}
server {
listen 80;
location /api/ {
proxy_pass <http://was/>;
}
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri /index.html;
}
location /ws {
proxy_pass <http://was/ws>;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
}
<aside> 📖
[/docker-entrypoint-initdb.d/
]
.sql
, .sql.gz
, .sh
파일을 넣어두면,
MariaDB가 초기화 과정에서 자동 실행.first run
)
해당 경로에 있는 스크립트를 자동 실행.
→ 최초로 컨테이너를 실행하거나, volume을 초기화했을 경우에만 실행
→ 이후 재시작 시에는 다시 실행되지 않는다.
→ 단, 하위 디렉토리가 있다면 해당 디렉토리에 있는 파일들은 실행되지 않는다.FROM mariadb:11.4
COPY ./sql /docker-entrypoint-initdb.d/
</aside>
nginx.conf 설정
events{}
http {
include /etc/nginx/mime.types; // 데이터 형식 확인
default_type application/octet-stream;
upstream was {
server backend:8080;
}
server {
listen 80; // 80 포트로 클라이언트 접속
location /api/ { // /api 형식으로 들어오는 url을 받아, api를 삭제.
proxy_pass <http://was/>; // upstream 에 설정한 was 로 넘겨준다.
}
location / { // / 형식으로 들어오는 url을 받는다.
root /usr/share/nginx/html; // 해당 폴더에 있는 Vue 컴포넌트들이 기준
index index.html; // 없으면 index.html 만 반환
try_files $uri /index.html;
// 있으면 해당 uri 에 맞는 컴포넌트를 index.html에 붙여 보낸다.
// SPA
}
location /ws { // /ws 형식으로 들어오는 url을 받아, 그대로 넘겨준다.
proxy_pass <http://was/ws>; // upstream 에 설정한 was 로 넘겨준다.
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
// Http는 기본적으로 단방향 연결이므로, 웹소켓 사용을 위해서 양방향 연결로 upgrade 수행
}
}
}
docker-compose.yml 작성
# 예시
version: "3"
services:
#서비스명
mariadb:
build:
context: ./mariadb
environment:
MARIADB_ROOT_PASSWORD: ${mariaPassword}
# 외부에서 주입
MARIADB_DATABASE: ${mariaDatabase}
# 외부에서 값 주입
volumes:
- ./mariadb/data:/var/lib/mysql
#서비스명
redis:
build:
context: ./redis
#서비스명
backend:
build:
context: ./server
environment:
SPRING_DATA_REDIS_HOST: redis
# 위쪽에 정의한 서비스 redis를 의미
SPRING_DATA_REDIS_PASSWORD: 1004
SPRING_DATASOURCE_URL: jdbc:mariadb://mariadb:3306/slgi_emr_db?useSSL=false
SPRING_DATASOURCE_USER: root
SPRING_DATASOURCE_PASSWORD: 1004
# 직접 값 작성
volumes:
- ./server/build/libs/server-0.0.1-SNAPSHOT.jar:/app/app.jar
depends_on:
- redis
- mariadb
#서비스명
frontend:
build:
context: ./frontend
ports:
- "80:80"
depends_on:
- backend
volumes:
- ./frontend/dist:/usr/share/nginx/html
<aside> 📖
[volume]
컨테이너가 생성 또는 삭제되어도 유지되는 데이터 저장소(디렉토리) → 컨테이너 데이터는 휘발성이 강하기 때문에, 삭제 또는 재시작시 데이터가 사라진다.
방법 | 설명 | 장점 | 단점 |
---|---|---|---|
Volume | Docker가 관리하는 저장소 | 관리 편리, 백업 용이, 성능 우수 | 호스트 디렉토리 직접 접근 어려움 |
Bind Mount | 호스트의 디렉토리를 명시적으로 지정 | 유연성 있음, 개발환경에 적합 | 경로가 하드코딩됨, 이식성 낮음 |
tmpfs | 휘발성 메모리 저장소 (리눅스 메모리 사용) | 빠름, 민감 데이터 일시 저장 | 휘발성, 영속성 없음 |
</aside> |
<aside> 📖
[depend_on]
컨테이너 간 의존관계 명시 → 특정 컨테이너가 다른 컨테이너 시작 이후 동작하도록 순서 지정에 사용
dockerignore 작성
https 설정
Git Action
문제
해결 과정
include /etc/nginx/mime.types;
default_type application/octet-stream;
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri /index.html;
}
$uri
가 2번 사용되어 text/plain 으로 읽는 문제였다.
→ $uri
를 1번만 사용하니 정상적으로 application/javascript로 인식.:ro
이용해 읽기전용으로만 실행시켜 보안성 확보 고려