Just Do IT!
Docker, Docker-compose 이용해서 가상머신에서 프로젝트 빌드하기 본문
요즘 docker 실습을 가상머신에서 하고 있다.
가상머신 설치 관련은 TIL 레파지토리에 이미 정리해서 블로그에도 정리해야 하나 고민 중이라,
우선은 내가 진행했던 프로젝트를 빌드해보는 걸 정리하려고 한다.
가상머신 설치 관련 정리:
https://github.com/seoyeon-jung/kosta-study-log/blob/master/16%EC%A3%BC%EC%B0%A8/240924/README.md
kosta-study-log/16주차/240924/README.md at master · seoyeon-jung/kosta-study-log
KOSTA TIL. Contribute to seoyeon-jung/kosta-study-log development by creating an account on GitHub.
github.com
이 블로그에서 다룰 프로젝트는
React + Spring 프로젝트이다. 아주 간단한 게시판 형식의 프로젝트이며 소셜 로그인이 포함되어있다.
로컬 환경에서는 구글, 깃허브, 카카오 로그인을 구현했지만 가상머신에서는 구글 로그인이 되지 않는다.
그래서 깃허브, 카카오 로그인만 확인해봤다.
.env 파일이나 소셜 로그인 관련 보안 키 등이 있기 때문에 private repository를 사용하여 front, back 폴더에 각 프로젝트를 복사하여 repository에 push해뒀다.
1. React 프로젝트
.env 파일 수정
가상머신을 사용하기 때문에 가상 머신의 ip 주소로 모든 uri를 변경해야 한다.
REACT_APP_REST_SERVER=가상머신IP주소/api
REACT_APP_GOOGLE_REDIRECT_URI=가상머신IP주소/oauth/google
REACT_APP_GOOGLE_ID=
REACT_APP_KAKAO_REDIRECT_URI=가상머신IP주소/oauth/kakao
REACT_APP_KAKAO_ID=558d1a2cd146034e29381ec3cd406e75
REACT_APP_GITHUB_REDIRECT_URI=가상머신IP주소/oauth/github
REACT_APP_GITHUB_ID=
나머지는 보인 키이기 때문에 각자의 보안 키를 추가하면 된다.
nginx.conf 파일 생성
이 파일은 nginx 기본 설정 파일이다. 여기서 nginx 설정을 할 수 있다.
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
- 하나의 서버 설정을 정의
- listen 80; : 서버가 HTTP 요청을 받을 포트를 지정
- server_name localhost; : 로컬에서 접속할 도메인 이름을 localhost로 지정
- root /usr/share/nginx/html; : 웹 서버가 파일을 제공할 기본 디렉토리를 지정
- index index.html : 클라이언트가 디렉토리를 요청할 때 기본적으로 제공할 파일 지정
- location / { ... } : 루트 URL (/)에 대한 요청을 처리하는 블록. 이 설정은 모든 요청에 대해 적용된다.
- try_files $uri $uri/ /index.html;
- 클라이언트가 요청한 URI를 기준으로 파일을 찾습니다.
- $uri: 요청된 경로와 일치하는 파일이 있는지 확인합니다.
- $uri/: 요청된 경로에 디렉토리가 있는지 확인합니다.
- /index.html: 위의 두 가지가 모두 실패할 경우, 기본적으로 index.html 파일을 반환
- HTTP 포트 80에서 localhost 도메인으로 들어오는 요청을 처리하고, 기본 웹 페이지로 index.html 파일을 제공하도록 구성
Dockerfile 생성
Dockerfile이란 docker 에서 이미지를 생성하기 위한 용도로 작성하는 파일이다.
만들 이미지에 대한 정보를 기술해 둔 템플릿(template) 이라고 보면 된다.
# 빌드 작업
# 1. Node 이미지 [20]
FROM node:20 AS build
# 2. 컨테이너에 작업 디렉토리 설정
WORKDIR /app
# 3. package.json, package-lock.json을 작업 디렉토리에 복사
COPY package*.json yarn.lock ./
# 4. 의존성 업데이트 및 설치
# RUN npm update
RUN yarn install
# 5. 소스 코드를 컨테이너에 복사
COPY . .
# 6. React 애플리케이션 빌드
RUN yarn run build
# 배포
# 1. Nginx 이미지
FROM nginx:alpine
# 2. Nginx 이미지 설정 파일을 교체
COPY nginx.conf /etc/nginx/conf.d/default.conf
# 3. Nignx 기본 html 삭제
RUN rm -rf /usr/share/nginx/html/*
# 4. 빌드된 React 애플리케이션을 Nginx 디렉토리로 복사
COPY --from=build /app/build /usr/share/nginx/html
# 5. Nginx 포트 노출
EXPOSE 80
# 6. Nginx 서버 실행
CMD [ "nginx", "-g", "daemon off;" ]
- daemon off;는 NGINX가 백그라운드에서 실행되지 않도록 하여 Docker가 컨테이너를 지속적으로 실행할 수 있게 한다.
다른 부분은 주석에 다 적어두었다.
docker-compose.yml 생성
Docker Compose는 여러 개의 도커 컨테이너를 정의하고 실행하기 위한 도구로, 단일 파일에 애플리케이션의 서비스, 네트워크, 볼륨 등을 설정할 수 있다.
docker-compose.yml 파일을 사용하여 여러 컨테이너 간의 관계와 설정을 정의하고, 한 번에 여러 컨테이너를 실행하거나 관리할 수 있다.
Docker Compose를 사용하면 복잡한 애플리케이션을 쉽게 정의하고 관리할 수 있으며, 개발 환경에서부터 프로덕션 배포까지 일관된 환경을 유지할 수 있다.
version: '3'
services:
front-image:
build:
context: .
container_name: front-container
ports:
- "80:80"
버전은 굳이 명시하지 않아도 되지만, 명시해줬고 프론트는 이렇게 하면 끝이다.
빌드
docker-compose up -d
docker compose를 사용하면 위의 명령어로 한번에 빌드가 가능하다.
처음 빌드하면 시간이 좀 걸리지만, 오타가 없다면 쉽게 빌드할 수 있다.
프로젝트를 수정하고 빌드하는 경우, 멈추고 삭제하고 다시 컨테이너를 빌드하지 않고
docker-compose up --build -d
이 명령어를 사용하면 손쉽게 다시 빌드할 수 있다.
아, 만약 깃허브와 연동되어있다면 git pull을 꼭 받아오고 다시 빌드해야 한다.
프로젝트 확인
이렇게 제대로 빌드되는 걸 확인할 수 있다.
2. Java 프로젝트
applicaiton.yml 파일 수정
- .env 파일 수정과 마찬가지로 가상 머신을 사용하므로 로컬로 되어있던 uri를 모두 수정해야 한다.
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://mysql-container:3306/market_db
username: root
password: 1234
oauth2:
clients:
google:
client-id:
client-secret:
redirect-uri: http://가상머신IP주소/oauth/google
token-uri: https://oauth2.googleapis.com/token
user-info-request-uri: https://www.googleapis.com/oauth2/v3/userinfo
kakao:
client-id:
client-secret:
redirect-uri: http://가상머신IP주소/oauth/kakao
token-uri: https://kauth.kakao.com/oauth/token
user-info-request-uri: https://kapi.kakao.com/v2/user/me
github:
client-id:
client-secret:
redirect-uri: http://가상머신IP주소/oauth/github
token-uri: https://github.com/login/oauth/access_token
user-info-request-uri: https://api.github.com/use
수정된 부분이다. 이 부분들을 수정해주면 된다.
Dockerfile 생성
도커는 컨테이너 간의 네트워크를 쉽게 설정할 수 있으므로, 별도의 리버스 프록시가 필요하지 않을 수 있다.
그래서 nginx.conf 파일 없이 Dockerfile만 생성해도 된다.
(이부분은 추가 공부가 좀 필요할 것 같다)
# build
# 빌드 이미지 (gradle)
FROM gradle:8-jdk17-alpine AS build
# 컨테이너 작업 디렉토리 설정
WORKDIR /app
# gradle 파일만 복사
COPY build.gradle settings.gradle gradlew ./
COPY gradle ./gradle
# 프로젝트 전체 파일 복사
COPY . .
# gradlew 파일에 권한 부여
RUN chmod +x gradlew
# 빌드 실행
RUN ./gradlew clean build -x test
# 실행
# openjdk 이미지
FROM openjdk:17-jdk-alpine
# 컨테이너 작업 디렉토리 설정
WORKDIR /app
# 빌드 단계에서 생성된 jar 파일 복사
COPY --from=build /app/build/libs/*.jar /app/app.jar
# port 노출
EXPOSE 8080
# 애플리케이션 실행
ENTRYPOINT [ "java", "-jar", "/app/app.jar" ]
docker-compose.yml 파일 생성
version: '3'
services:
mysql:
image: mysql:8
container_name: mysql-container
environment:
- MYSQL_ROOT_PASSWORD=1234
- MYSQL_USER=sy
- MYSQL_PASSWORD=1234
- MYSQL_DATABASE=market_db
- TZ=Asia/Seoul
ports:
- "3306:3306"
networks:
- market-net
back-image:
build:
context: .
container_name: back-container
ports:
- "8080:8080"
environment:
- SPRING_DATASOURCE_URL=jdbc:mysql://mysql-container:3306/market_db
- SPRING_DATASOURCE_USERNAME=root
- SPRING_DATASOURCE_PASSWORD=1234
networks:
- market-net
depends_on:
- mysql
restart: always
networks:
market-net:
driver: bridge
백엔드 파트는 yml 파일 설정할 것들이 좀 있다.
내가 올리려는 프로젝트는 mysql을 db로 사용하고 있기 때문에 mysql과 java 프로젝트가 서로 연결되어야 한다.
이때 docker network를 사용한다.
- 두 컨테이너를 연결해주기 위한 네트워크 생성
- 컨테이너가 동일한 네트워크에 속해 있다면 서로의 이름으로 접근할 수 있다.
- 네트워크를 사용하면 애플리케이션의 각 구성 요소(예: 데이터베이스, 웹 서버 등)를 분리하고 관리하기 용이해진다.
이러한 특징을 가지고 있는 network인데,
명령어를 통해 생성할 수 있지만 번거로우므로 docker-compose.yml 파일에 함께 추가하여 생성하는게 편하다.
또한,
- mysql보다 백엔드 서버가 먼저 실행되는 경우 오류가 발생할 수 있다.
- 이를 방지하기 위해 depends_on을 추가해주고, restart: always도 추가한다.
이 부분도 중요하다.
백엔드 서버보다 mysql이 먼저 실행되어야 오류가 발생하지 않으므로 추가해줘야 한다.
빌드
아까 명령어와 동일하게 실행해주면 실행된다.
docker-compose up -d
이렇게 현재 실행되는 docker 리스트를 출력해보면 정상적으로 세 가지 컨테이너가 실행됨을 알 수 있다.
프로젝트 확인
이렇게 백엔드와 프론트가 서로 잘 연동되어 db에도 쌓이는 걸 확인할 수 가 있다.
요즘 가상머신으로 docker 관련 실습을 반복하고 있는데, 이 흐름을 좀 알아야 할것 같다는 생각이 든다.
오늘도 이렇게 잘 생성되는 걸 확인했지만 이 원리를 좀 더 알아보고 싶다.
그래도 나중에 혼자 실습할 때 참고하고 싶어서 글로 정리해본다.
'개발 공부 > DevOps' 카테고리의 다른 글
Docker와 Docker Compose (5) | 2024.09.27 |
---|---|
Nginx란 무엇인가? (1) | 2024.09.24 |