도커를 공부하면서 docker run
이나 docker-compose
명령어로 설정한 환경으로 서버를 활성화 하는 과정이 신기해서 docker-compose up
을 이용해서 프론트 + DB + 서버를 한번에 실행하는 코드를 만들었습니다.
한번에 실행되는 뽕에 취해서 시도한 방법이지만 단점이 더 많아서 다음부터는 무조건 분리해야겠습니다.
우선 도커를 어떤 과정으로 만들었는지 소개합니다.
로컬 환경에서 테스트 서버를 만드는 설정파일 입니다.
docker-compose up --build
명령어를 통해서 코드에 변화가 생긴다면 아래 yml설정대로 새로운 이미지를 만들게 됩니다.
version: '3.9'
services:
database:
build: ./database
restart: always
volumes:
- mysql-volume:/var/lib/mysql
environment:
- MYSQL_USER=${HS512_SECRET}
- MYSQL_PASSWORD=${HS512_SECRET}
- MYSQL_ROOT_PASSWORD=${HS512_SECRET}
- MYSQL_DATABASE=${HS512_SECRET}
expose:
- 3306
ports:
- "3306:3306"
springboot-server:
depends_on:
- database
build: ./springboot-server
restart: always
volumes:
- ./springboot-server:/build/app
expose:
- 8080
ports:
- "8080:8080"
environment:
- MYSQL_HOST=database
- MYSQL_USER=${HS512_SECRET}
- MYSQL_PASSWORD=${HS512_SECRET}
- MYSQL_DATABASE=${HS512_SECRET}
- MYSQL_PORT=3306
- HS512_SECRET=${HS512_SECRET}
volumes:
mysql-volume:
depends_on
은 의존하는 서비스가 실행될 때 해당 서비스를 시작하게 됩니다.
이때 스프링의 jdbc manager
가 연결할 때 db가 아직 켜지는 중이면 에러가 발생하므로 restart
를 추가해서 다시 시도하도록 했습니다.
도커를 처음해서 테스트 한다고 db와 서버를 동시에 켰는데 db는 RDS
로 켜놓는게 정신건강에 좋을것 같습니다.
docker-compose.yml
에서 volumes:
로 프로젝트 파일을 볼륨에 복사할 수 있지만 권한 설정을 줄 수 없어서 Dockerfile
에서 복사를 했습니다.
마찬가지로 db생성 시 필요한 설정을 추가하기 위해서 command:
를 이용했지만 적용되지 않아서 스크립트를 만들어 Dockerfile
에서 권한을 부여한 후 복사를 했습니다.
각 서비스에서 사용하는 환경변수는 environment:
로 넣어줬습니다.
Dockerfile
에서는 이미지를 만들기 위한 파일 복사와 실행할 스크립트 생성 및 권한 부여를 했습니다.
From
다음에는 도커허브에서 다운받을 이미지를 명시합니다. ( mysql:5.7 )
FROM mysql:5.7
# 도커 디렉토리로 설정 파일 복사
COPY ./scripts/ /docker-entrypoint-initdb.d/
COPY ./01-database.sh /docker-entrypoint-initdb.d/
RUN sed -i 's/\r$//' /docker-entrypoint-initdb.d/01-database.sh
COPY ./my.cnf /etc/mysql/conf.d/my.cnf
RUN chmod 644 /etc/mysql/conf.d/my.cnf
RUN chmod 755 /docker-entrypoint-initdb.d/01-database.sh
sed -i 's/\r$//'
를 이용해서 윈도우 환경에서 작성된 스크립트를 리눅스 환경에서 작동하도록 개행문자를 수정합니다.
docker는 /etc/mysql/conf.d/my.cnf
를 참조해서 db를 설정합니다.
아래 코드로 타임과 utf-8설정을 추가합니다.
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
default-time-zone=Asia/Seoul
[mysql]
default-character-set=utf8mb4
[client]
default-character-set=utf8mb4
[mysqldump]
default-character-set=utf8mb4
테이블을 생성하기 전에 설정할 데이터베이스를 스크립트로 만들었습니다.
#!/bin/bash
# 데이터베이스 생성
mysql -u root -p$MYSQL_ROOT_PASSWORD -e "CREATE DATABASE ${MYSQL_DATABASE};"
# 사용자에게 데이터베이스에 대한 권한 부여
mysql -u root -p$MYSQL_ROOT_PASSWORD -e "GRANT ALL PRIVILEGES ON ${MYSQL_DATABASE}.* TO $MYSQL_USER@'%';"
# 생성한 데이터베이스 선택
mysql -u $MYSQL_USER -p$MYSQL_PASSWORD -e "USE $MYSQL_DATABASE;"
도커에서 mysql 이미지를 만들때 /docker-entrypoint-initdb.d/
를 참조합니다.
내부에 있는 파일들을 이름 순서대로 실행하므로 숫자로 순서를 지정했습니다.
01-database.sh
-> 02-create_table.sql
-> 03-insert_data.sql
FROM gradle:7.4-jdk-alpine AS builder
# 작업 디렉토리 설정
WORKDIR /build
# 도커 캐시 사용 - 새로운 Gradle만 다운로드
COPY build.gradle settings.gradle /build/
RUN gradle build -x test --parallel --continue > /dev/null 2>&1 || true
# 스프링 프로젝트 복사
COPY . /build
RUN gradle clean build --parallel
# Java 11 JDK 가 설치된 Docker 이미지를 기반으로 새 이미지 생성
FROM openjdk:11.0-slim
WORKDIR /app
# 빌드한 jar파일을 /app.jar 로복사
COPY --from=builder /build/build/libs/*.jar /app.jar
# root 권한 x, nobody 권한으로 실행함
USER nobody
ENTRYPOINT [ \
"java", \
"-Dspring.profiles.active=prod", \
"-Dfile.encoding=UTF-8", \
"-Djava.security.egd=file:/dev/./urandom", \
"-Dsun.net.inetaddr.ttl=0", \
"-jar", \
"/app.jar" \
]
jar를 만들기 위해서 Gradle
이미지를 복사합니다.
이때 캐시를 이용해서 새로운 버전이 생길 경우만 새로운 이미지를 다운 받습니다.
RUN gradle clean build --parallel
명령어로 jar파일을 생성합니다.
이때 제가 만든 서버에서는 clean build
시 테스트를 하고 RestDocs 문서를 만들어 jar에 넣게됩니다.
jar를 실행하기 위해 jdk 이미지를 넣은 뒤 이미지를 실행하는 ENTRYPOINT를 추가합니다.
# 변경을 감지해 새로운 이미지 빌드 후 싪행
docker-compose up --build
# 이미지를 실행
docker-compose up
루트 프로젝트 위치에서 터미널에 위 커맨드를 입력하면 docker-compose
가 루트 디렉토리의 docker-compose.yml
을 찾아서 설정파일대로 이미지를 만들기 시작합니다.
한번 설정하면 다음부터는 손쉽게 서버를 켜서 개발을 진행할 수 있게 됩니다.
이미지를 빌드 했었다면 Docker Desktop
을 이용해서 클릭 한 번으로 서버를 켤 수도 있습니다.
만약 리액트 서버를 도커에 추가한다면 아래 방법을 이용합니다.
version: '3.9'
services:
react-app:
build: ./react-app
volumes:
- ./react-app:/home/node/app
expose:
- 3000
ports:
- "3000:3000"
Dockerfile
FROM node:14.18.1-bullseye
WORKDIR /home/node/app
# package.json 을 Docker 이미지에 복사
COPY package*.json ./
RUN npm cache clean --force
RUN npm install
# 앱 소스를 Docker 이미지에 복사
COPY . .
CMD ["npm", "start"]
node이미지를 다운받아 npm을 이용해서 package*.json
설정대로 리액트 의존성을 다운받습니다.
이후 npm start
명령어를 실행해서 리액트 서버를 실행합니다.