이전 게시글에선 서버에서 직접 어플리케이션 소스 코드를 다운받아 빌드하는 배포 방식을 사용했다면, 이번엔 도커를 사용하여 어플리케이션을 이미지로 만들어 배포하는 방식을 사용할 것이다. 따라서 본 게시글엔 이미지 배포의 첫번째 단계인 도커를 통한 이미지 빌드 방식을 서술하려고 한다.
Docker
일관성 있는 운영환경의 중요성이 강조됨에 따라 컨테이너를 통한 배포 방식이 주를 이루며 사용되고 있다. 또한 어플리케이션의 코드 상의 문제를 테스트 코드에서 검증했다면, 운영상의 서버 설정 문제를 컨테이너에서 검증할 수도 있다.
Dockerfile? docker-compose?
docker를 처음 사용하려고 보면 어떤 곳에선 Dockerfile을, 어떤 곳에선 docker-compose를 사용하고 있다. 어떤 차이점이 있을까?
어플리케이션을 실행하기 위해선 데이터베이스, 캐시, 메세징 큐 등 다양한 인프라(혹은 MSA라면 다른 어플리케이션)가 필요하다. docker에서도 어플리케이션을 실행하기 위해 이러한 인프라들을 함께 실행해주어야 한다. 이러한 역할을 하는 것이 docker-compose 파일이다.
Dockerfile이 단일 이미지를 빌드하기 위한 파일이라면 docker-compose는 이미지들을 오케스트레이션하여 실행될 수 있도록 해준다. docker-compose 에서 이미지들의 dependency, network 등을 설정할 수 있다. 참고
Docker-compose 설정 (MySQL)
docker-compose.yml
version: '3'
services:
database-mysql:
container_name: database-mysql
image: mysql/mysql-server:8.0
environment:
MYSQL_ROOT_PASSWORD: 'simple'
MYSQL_ROOT_HOST: '%'
MYSQL_DATABASE: 'simple'
TZ: Asia/Seoul
volumes:
- ./mysql-init.d:/docker-entrypoint-initdb.d
ports:
- '13306:3306'
command:
- '--character-set-server=utf8mb4'
- '--collation-server=utf8mb4_unicode_ci'
database-adminer:
container_name: database-adminer
image: adminer:latest
ports:
- "18080:8080"
environment:
- ADMINER_DEFAULT_SERVER=database-mysql
- ADMINER_DESIGN=hydra
- ADMINER_PLUGINS=tables-filter tinymce
spring boot에 mysql을 적용하기 전 설정을 해보자. mysql을 gui로 관리하기 위해 adminer도 추가해주었다. compose 설정의 더 자세한 사항은 공식문서 참고
version
사용할 docker-compose의 버전을 지정해준다. 버전별로 문법이 다를 수 있으니 유의하자.
services
실행할 서비스들을 정의해준다. 하위에 있는 database-mysql, database-adminer가 서비스의 이름으로 정의된다. 이때 꼭 유의해야 할 점이, compose에 정의된 서비스들 사이에선 이 서비스 이름으로 통신을 한다. 따라서 localhost가 아닌 서비스 이름으로 url을 지정해주어야 한다. 자세한 사항은 spring에서 mysql에 connect할 때 보자.
container_name
커스텀한 container 이름을 설정할 수 있도록 해준다.
container 와 image 차이
사용자가 설정한 템플릿을 이미지라고 한다면 이 이미지를 실행한 상태를 컨테이너라고 한다. 자바로 치면 클래스를 이미지라고 한다면 인스턴스는 컨테이너 같은 관계이다.
image
사용할 이미지와 버전을 설정해준다. 도커 허브에 있는 이미지를 사용할 수도 있고 직접 정의한 이미지를 사용할 수도 있다.
ports
'호스트에서 접속할 외부 포트:도커 내부의 실제 포트' 로 정의해준다.
여기에서 꽤 삽질을 했는데.. 13306:13306으로 설정하면 도커가 자동으로 mysql 포트를 13306으로 설정해주지 않을까? 했다가 계속 되는 connection error로 많은 시간을 허비했다..
또한 docker-compose 의 이미지들 간의 통신은 도커 내부 포트를 사용한다. (여기서 또 삽질..)
environment
해당 이미지가 사용할 환경변수를 설정해준다.
command
컨테이너가 실행될 때 함께 수행될 명령어를 정의한다.
volume
호스트의 파일과 도커의 사이의 마운트할 볼륨을 지정해준다.
해당 파일에선 데이터베이스를 초기화 해주기 위한 용도로 사용해주었다.
mysql-init.d 폴더의 파일이 컨테이너의 docker-entrypoint-initdb.d 폴더에 마운트 되어, 도커가 처음 시작되었을 때 해당 폴더의 sql 파일들이 실행된다.
/mysql-init.d/init.sql
CREATE USER 'simple'@'localhost' IDENTIFIED BY 'simple';
CREATE USER 'simple'@'%' IDENTIFIED BY 'simple';
GRANT ALL PRIVILEGES ON *.* TO 'simple'@'localhost';
GRANT ALL PRIVILEGES ON *.* TO 'simple'@'%';
CREATE DATABASE simple DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
유저와 데이터베이스를 생성하는 초기화 코드를 작성해주었다.
이제 docker-compose.yml 파일이 있는 폴더에서
$ docker-compose up -d
명령어를 통해 실행해보자.
adminer를 통해 데이터베이스에 접근할 수 있다!
application.yml
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:13306/simple
username: root
password: simple
위와 같이 application.yml에 property를 설정하여 로컬의 스프링 어플리케이션에서 데이터베이스로 접근해보자.
docker-compose에서 설정한 외부 포트와 데이터베이스를 통해 연결할 수 있다.
Docker Image Build
이제 스프링 부트도 docker로 실행하기 위해 이미지로 만들어야 한다.
이번엔 Dockerfile로 이미지를 생성하여 docker-compose에서 사용해보자.
또한 배포용 스프링 profile을 설정하여 배포용 환경 설정을 추가하자.
Dockerfile
FROM openjdk:11-jdk
RUN apt-get update && apt-get -y install sudo
ARG JAR_FILE="build/libs/simple-*.jar"
COPY ${JAR_FILE} app.jar
ENV PROFILE dev
ENTRYPOINT ["java", "-Dspring.profiles.active=${PROFILE}", "-jar","/app.jar"]
openjdk 11을 사용하여 build한 jar 파일을 실행하는 명령어이다.
이때 -Dspring.profiles.active 를 사용하여 실행할 어플리케이션의 프로파일을 설정해준다.
설정된 프로파일에 따라 application 설정 파일을 다르게 실행할 수 있다. 위 파일에선 dev로 설정해주었으므로 application-dev.yml 파일에 정의된 설정대로 어플리케이션이 실행된다.
application-dev.yml
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://database-mysql:3306/simple
username: root
password: simple
로컬에서 실행한 application.yml과 다른 점은 database에 접근하는 url과 port가 달라졌다는 것 이다.
이미지는 docker-compose 에서 설정한 컨테이너에서 실행되기 때문에 url은 localhost가 아닌 docker의 서비스 이름을, port는 외부 포트가 아닌 내부 포트로 변경되었다.
docker-compose.yml
application:
container_name: app-simple
build: ../
restart: always
ports:
- '80:8080'
depends_on:
- database-mysql
docker-compose 파일도 spring profile 처럼 docker-compose.dev.yml 과 같이 프로파일을 설정해줄 수 있다. 필요하다면 참고하자.
build
Dockerfile을 통해 이미지를 빌드했을 경우 사용해주는 설정이다. Dockerfile이 아닌 다른 이름으로 파일을 저장했을 경우 dockerfile option을 통해 지정해줄 수 있다. 나는 다음과 같이 파일을 설정했기 때문에 Dockerfile의 context를 ../로 지정해주었다.
depends_on
depends_on과 유사한 links 설정이 있는데, deprecated 되었다고 하니 유의하자.
다시 docker-compose up -d 를 통해 실행하면 스프링이 잘 동작하는 것을 볼 수 있다!
다음엔 ecs, ecr을 통해 이미지를 배포해보자
'Devops > CD' 카테고리의 다른 글
[Github Action] CodeDeploy와 S3를 이용하여 배포하기 (0) | 2022.03.25 |
---|