실제 사용예시 (핵심만 보기용도)
- docker-compose를 사용할만한 상황으로, multimodule 환경을 구성해보았다.
Multimodule(루트 프로젝트)
- api-other (모듈)
- api_center (모듈)
- api_common (모듈)
여기서 나는 이미지를 찍고 컨테이너화 하고싶은 모듈이 api-other와 api_center이다.
2. 컨테이너화 하고싶은 모듈인 api-other와 api_center 모듈 안에 각각 Dockerfile을 생성한다
현재 api-other와 api_center의 application 내용은 아래와 같다
- api-other
package com.example.apiother;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@SpringBootApplication
public class ApiOtherApplication {
@GetMapping("/")
public String show() {
return "api-other 모듈 노출내용";
}
public static void main(String[] args) {
SpringApplication.run(ApiOtherApplication.class, args);
}
}
- api_center
*현재 module 연동을 해놓은 것이여서 아래와 코드가 있으나, 해당 HTTP method로 접근하게 되면 "Common 모듈을 연동하여 Center에서 출력" 문구가 출력됨
package com.center.module.controller;
import com.center.module.ExService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RequiredArgsConstructor
@RestController
public class ExController {
private final ExService exService;
@GetMapping("/")
public String selectName(){
return exService.selectName();
}
}
3. 이전에 생성했던 Dockerfile 2개를 관리하기 용이하게, 루트 프로젝트 단위에 docker-compose.yml 파일 생성
전체 코드는 아래와 같다
# 버전 정의, 버전마다 지원하는 형식이 다름
version: '3.8'
# docker-compose로 생성할 container의 옵션을 정의
services:
api-other:
# docker-compose build 옵션에서 사용되는 build 옵션을 기재
build:
# Dockerfile의 위치를 파악 후 지정
context: ./api-other
# Dockerfile 이름 파악 후 지정
dockerfile: Dockerfile
# 저장할 컨테이너 이름 지정
container_name: api-other
# 컨테이너 내부에서 구동하는 애플리케이션은 8080포트 (오른쪽)을 사용하고 있음
# 아래와 같이 포트포워딩을 함으로써, 호스트에서 8080포트 (왼쪽)으로 들어오는 요청은 컨테이너 내부 8080포트 (오른쪽)으로 전달됨
# 이로써 호스트 컴퓨터와 컨테이너간에 통신이 가능해지며, 컨테이너 내부의 애플리케이션에 접근할 수 있게됨
ports:
- "8080:8080"
# 이하 동일함
api-center:
build:
context: ./api_center
dockerfile: Dockerfile
container_name: api-center
ports:
- "8081:8080"
추가정보
- 서로 다른 호스트 포트를 지정하는 이유가 뭘까?
여러 개의 컨테이너를 호스트에서 실행할 때 포트 충돌을 피하기 위해서 서로 다른 포트를 지정하는 것!!!
아래와 같이 작성해야 두 개의 서비스를 포트 충돌없이 동시에 실행할 수 있습니다.
version: '3.8'
services:
service1:
image: my-image1
container_name: my-service1
ports:
- "8001:80"
service2:
image: my-image2
container_name: my-service2
ports:
- "8002:80"
4. 위에 언급되었던 docker-compose 명령문을 통해 이미지 생성 및 실행을 진행!!!
- docker-compose up -d 명령문 실행
도커 이미지 생성 및 실행이 모두 완료됨.
5. 정상작동 되는지 확인
아주 좋습니다
도커를 공부하다보니 궁금한 점이 생겼다. 원하는 어플리케이션을 도커에 띄울 때
dockerFile 을 사용하기도 하고 docker-compose.yml 을 사용하기도 한다.
왜 둘이 분리해놓은 것일까? 다른 점은 무엇일까?
Dockerfile
- Dockerfile은 DockerImage를 생성하기 위한 스크립트(설정파일)
- base image 파일로 수정된 image 만드는 일련의 과정들을 정리해 놓은 파일
- 여러가지 명령어를 토대로 Dockerfile을 작성한 후 빌드하면 Docker는 Dockerfile에 나열된 명령문을 차례대로 수행하며 DockerImage를 생성
⇒ Dockerfile을 읽을 줄 안다는 것은 해당 이미지가 어떻게 구성되어 있는지 알 수 있다는 의미
→ Dockerfile : 이미지를 어셈블하기 위해 호출할 수 있는 명령이 포함된 간단한 텍스트 파일
즉, base image 파일로부터 수정된 image를 만드는 일련의 과정들을 정리해 놓은 파일이며, docker는 이 Dockerfile을 이용해 손쉽게 바로 동일한 이미지를 반복적으로 생성할 수 있다.
Dockerfile의 장점
- (1) 이미지가 어떻게 만들어졌는지를 기록한다.
- 보통 사람들은 완성된 이미지를 가져다 쓰기 때문에 이미지가 어떻게 만들어졌는지에 대해서는 알 필요가 없다. 그러나 개발자의 경우라면 조금 다르다. 어떠한 애플리케이션을 담고 있는 이미지가 설치 되기 위한 과정은 어떠한지, 중간에 어떠한 과정을 수정해야 하는지 등을 알아야 하는 경우가 있다.
- 이는 Dockerfile이 자동화된 스크립트 형태이기 때문이다.
- (2) 배포에 용이하다.
- 어떠한 이미지를 배포할 때, 몇 기가씩이나 되는 이미지 파일 자체를 배포하기보다는 그 이미지를 만들 수 있는 스크립트인 Dockerfile만을 배포한다면 매우 편리할 것이다.
- 사용자는 그 스크립트를 실행시키기만 하면 스스로가 그 Dockerfile에 해당하는 이미지를 얻을 수 있기 때문이다.
- 실제로 Docker Hub에 가면, Dockerfile로 이미지를 배포하고 있는 사람들을 심심찮게 볼 수 있다. 물론 이미지로 배포하는 사람도 있지만.
- (3) 컨테이너(이미지)가 특정 행동을 수행하도록 한다.
- 컨테이너 환경에서 애플리케이션을 개발하다 보면, 특정 행동을 취하도록 하는 컨테이너를(이미지를) 만들어야 할 때가 있다.
- 이는 사실 말로서 설명하기는 좀 어렵고, 실제 개발을 하다보면 '아, 이거 Dockerfile 쓰면 좀 간단해 지겠구나...' 라는 생각이 머릿속에서 불현듯 번개처럼 스칠때가 있다.
여기까지 Dockerfile을 통한 이미지 생성방식이다.
하지만 이런 식으로 이미지를 만들 시에는 통상 아래와 같이 작업이 진행될 것이다.
- 애플리케이션 build를 통해 jar 혹은 war 파일 만듦
- Dockerfile을 통하여 원하는 베이스 이미지에 빌드된 결과물을 저장
- 이지미 생성
여기서 의문점이 하나 생긴다
“하나의 서비스를 만들 때 오직 1개의 도커 이미지를 활용하는 것도 좋지만 세세하게 관리하는데 있어서는 좋지 않은 편인 것 같다.
그러면 세세하게 나눠 배포하는 게 관리 측면에서 여러모로 좋을텐데?
즉, 하나의 서비스를 만들 때 복수의 도커 이미지를 핸들링하는 상황이 필요하게 된다면?”
그래서 생겨난 것이 docker-compose이다.
docker-compose는 Docker에 대한 새롭고 특수한 기능을 사용하는 것이 아닌, 기존 Docker에 대한 기능을 거의 다 그대로 사용한다. 단지 복수의 컨테이너를 동시에 시작하거나, 리로드하거나, 등의 핸들링 기능 위주로 존재한다.
즉! docker-compose를 사용하지 않는다는 이유로 특정 기능을 사용하지 못해 서비스 배포에 문제가 생기는 건 전혀없다. 단지 조금 더 체계적이고 깔끔해진다는 점이 존재한다.
docker-compose
- 연결된 다수의 container를 하나로 통합하여 관리하는 도구
- 다중 컨테이너 Docker 애플리케이션을 정의하고 실행하기 위한 도구로 앱을 구성하는 서비스를 docker-compose.yml에 정의하여 docker-compose up 명령어로 앱을 실행할 수 있다.
- docker-compose.yml은 container실행 옵션을 미리 정의한 문서이다.
- docker-compose.yml에 빌드 명령을 추가하면 Docker compose는 DockerFile를 사용한다.
- 웹 서비스는 일반적으로 프론트엔드 서버, 백엔드 서버, DB서버로 구성되기 때문에 각 서버를 docker container로 연결하여 동작시키고 docker compose를 사용하여 해당 컨테이너들을 관리하는 것 권장
→ Docker Compose : 앱을 구성하는 서비스를 docker-compose.yml에 정의하여 docker-compose up을 실행하여 하나의 명령으로 앱을 실행
즉, 앱이 실행되는 동안 컨테이너를 관리하는 역할앱이 시작되면 컨테이너를 띄우고 앱이 실행되는 중에 컨테이너가 종료되면 다시 띄워줌
조금 더 쉽게 말하자면, docker-compose는 연결된 다수의 Container를 하나로 통합하여 관리하는 도구이고, host level에서만 동작하며, Container 실행 옵션을 미리 정의한 문서인 docker-compose-yml을 기반으로 Container를 실행한다.
Dockerfile에 빌드 관련 내용이 다 기재되어 있기 때문에 docker-compose.yml에서는 따로 빌드 관련 내용을 기재할 필요 없이 Dockerfile의 경로를 지정하기만 하면 된다.
docker-compose.yml 기본형식
# 버전을 정의하는 것으로 버전에 따라 지원하는 형식이 다르다.
version: "3.0"
# docker-compose로 생성 할 container의 옵션을 정의한다.
services:
# 생성 할 container 이름을 지정한다.
[container 이름]:
# container 생성시 사용 할 이미지를 지정한다.
image: [image 이름]:[버전]
# docker-compose build 옵션에서 사용되는 build 옵션을 기재한다.
# dockerfile에 명시된 FROM의 image를 사용하여 위에 명시된 image 이름과 tag로 새로운 image를 생성한다.
build:
# dockerfile의 위치를 지정한다.
context:
# container port mapping 정보
ports:
- "80:80"
# 도커 컨테이너가 실행되었을 때 요청 대기할 포트를 지정한다.
# 여러 포트 지정도 가능하다.
expose:
- "80"
# 환경 변수 리스트 정의
environment:
key: "value"
# 실행 환경 설정
stdin_open: true # docker run -i
tty: true # docker run -t
entrypoint: /bin/bash # exec /bin/bash
dockerfile, docker-compose.yml 예시
아래의 docker-compose.yml 파일의 내용은 아래의 docker 명령어 두 개를 수행하는 내용이다.
- docker build -t ubuntu_base_web:v1 ./
- docker run -p 80:80
dockerfile
FROM openjdk:17-jdk
# JAR_FILE 변수 정의 -> 기본적으로 jar file이 2개이기 때문에 이름을 특정해야함
# 나는 그냥 bootJar해서 jar file 1개만 생성한 후 아래와 같이 진행했음
ARG JAR_FILE=./build/libs/docker-0.0.1-SNAPSHOT.jar
# JAR 파일 메인 디렉토리에 복사
COPY ${JAR_FILE} app.jar
# 시스템 진입점 정의
ENTRYPOINT ["java","-jar","/app.jar"]
docker-comopse.yml
version: "3"
service:
db:
image: mysql:5.7
restart: always
volumes:
- ./mysqldata:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=dgkcoding
- MYSQL_DATABASE=dgkdb
ports:
- "3306:3306"
기본적으로 docker-compose.yml은 version, services, volumes, networks의 카테고리로 작성된다.
하지만, 주로 version과 services가 많이 사용된다.
- version
docker compose의 파일 포맷 버전을 지정한다.
기본적으로 버전 3을 사용하는 것이 일반적이다.
- services
한개 또는 여러 개의 docker container를 설정한다.
- image
docker container의 이름을 정의한다.
Docker Hub에 있는 이미지를 사용하여 docker container를 작성할 경우 image를 설정할 수 있다.
- restart
docker container가 다운되었을 경우, 항상 재시작하라는 설정이다.
- volumes
docker run 명령의 -v 옵션과 동일한 역할을 한다.
여러 개의 volume을 지정할 수 있으며 리스트처럼 작성하면 된다.
- environment
dockerfile의 ENV 옵션과 동일한 역할을 한다.
- ports
docker run 명령의 -p 옵션과 동일한 역할을 한다.
참고로, 포트번호를 입력할 때에는 반드시 쌍따옴표 안에 작성해야 한다. (YAML 문법에서 숫자:숫자 는 시간으로 해석하기 때문)
- networks
docker container 간의 네트워크 분리를 위해 추가로 설정을 한다. (옵션)
docker-compose 커맨드 사용법
f 옵션
Docker Compose는 기본적으로 커맨드가 실행하는 디렉토리에 있는 docker-compose.yml 또는 docker-compose.yaml를 설정 파일로 사용합니다. 다른 이름이나 경로의 파일을 Docker Compose 설정 파일로 사용하고 싶다면 -f 옵션으로 명시를 해줍니다.
$ docker-compose -f docker-compose-local.yml up
-f 옵션은 여러 개의 설정 파일을 사용할 때도 사용할 수 있습니다. 이 때는 나중에 나오는 설정이 앞에 나오는 설정보다 우선하게 됩니다.
$ docker-compose -f docker-compose.yml -f docker-compose-test.yml up
up
docker-compose up 커맨드는 아마도 Docker Compose에서 가장 자주 사용되는 커맨드일 텐데요. Docker Compose에 정의되어 있는 모든 서비스 컨테이너를 한 번에 생성하고 실행하기 위해서 사용합니다.
보통 -d 옵션을 사용하여 백그라운드에서 컨테이너를 띄우는 경우가 많습니다.
$ docker-compose up -d
Creating network "django-app_default" with the default driver
Creating django-app_db_1 ... done
Creating django-app_web_1 ... done
$
-d 옵션을 사용하지 않으면 현재 터미널이 컨테이너의 로그가 출력되고 Ctrl + C를 눌러서 탈출하는 순간 컨테이너가 모두 정지되기 때문입니다.
down
docker-compose down 커맨드는 docker-compose up 커맨드와 정반대의 동작을 합니다. Docker Compose에 정의되어 있는 모든 서비스 컨테이너를 한 번에 정지시키고 삭제합니다.
$ docker-compose down
Stopping django-app_web_1 ... done
Stopping django-app_db_1 ... done
Removing django-app_web_1 ... done
Removing django-app_db_1 ... done
Removing network django-app_default
start
docker-compose start 커맨드는 내려가 있는 있는 특정 서비스 컨테이너를 올리기 위해서 사용합니다. 대부분의 경우에는 docker-compose up 커맨드를 사용해도 내려간 서비스를 알아서 올려주므로 무방합니다.
$ docker-compose start web
Starting web ... done
stop
docker-compose stop 커맨드는 docker-compose start 커맨드와 정반대의 동작을 합니다. 돌아기고 있는 특정 서비스 컨테이너를 정지시키기 위해서 사용합니다.
$ docker-compose stop web
Stopping django-app_web_1 ... done
ps
docker-compose ps 커맨드는 Docker Compose에 정의되어 있는 모든 서비스 컨테이너 목록을 조회할 때 사용합니다.
$ docker-compose ps
Name Command State Ports
----------------------------------------------------------------------------------
django-app_db_1 docker-entrypoint.sh postgres Up 5432/tcp
django-app_web_1 python manage.py runserver ... Up 0.0.0.0:8000->8000/tcp
logs
docker-compose logs 커맨드는 서비스 컨테이너의 로그를 확인하고 싶을 때 사용하며, 보통 -f 옵션을 붙여서 실시간 로그를 확인합니다.
$ docker-compose logs -f web
Attaching to django-app_web_1
web_1 | Watching for file changes with StatReloader
web_1 | Performing system checks...
web_1 |
web_1 | System check identified no issues (0 silenced).
web_1 |
web_1 | May 30, 2020 - 22:16:29
web_1 | Django version 3.0.6, using settings 'our_project.settings'
web_1 | Starting development server at <http://0:8000/>
web_1 | Quit the server with CONTROL-C.
exec
docker-compose exec 커맨드는 실행 중인 서비스 컨테이너를 대상으로 어떤 명령어를 날릴 때 사용합니다.
$ docker-compose exec db psql postgres postgres
psql (12.2 (Debian 12.2-2.pgdg100+1))
Type "help" for help.
postgres=#
run
docker-compose run 커맨드는 서비스 컨테이너의 특정 명령어를 일회성으로 실행할 때 사용합니다.
$ docker-compose run web env
PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=10757eb6642e
TERM=xterm
LANG=C.UTF-8
GPG_KEY=E3FF2839C048B25C084DEBE9B26995E310250568
PYTHON_VERSION=3.8.2
PYTHON_PIP_VERSION=20.1
PYTHON_GET_PIP_URL=https://github.com/pypa/get-pip/raw/1fe530e9e3d800be94e04f6428460fc4fb94f5a9/get-pip.py
PYTHON_GET_PIP_SHA256=ce486cddac44e99496a702aa5c06c5028414ef48fdfd5242cd2fe559b13d4348
PYTHONUNBUFFERED=1
HOME=/root
config
docker-compose config 커맨드는 Docker Compose 설정을 확인할 때 사용합니다. -f 옵션으로 여러 개의 설정 파일을 사용할 때, 최종적으로 어떻게 설정이 적용되는지 확인해볼 때 유용합니다.
docker-compose config
services:
db:
environment:
POSTGRES_PASSWORD: postgres
POSTGRES_USER: postgres
image: postgres
web:
build:
context: /Users/dale/temp/django-app
command: python manage.py runserver 0:8000
depends_on:
- db
ports:
- 8000:8000/tcp
volumes:
- /Users/dale/temp/django-app:/web:rw
version: '3.0'
'개인공부' 카테고리의 다른 글
자동 build Tool별 특징 및 장단점 (0) | 2023.05.20 |
---|---|
헥사고날 아키텍처 개념 및 사용법 (0) | 2023.05.05 |
Multimodule(멀티모듈) 개념 및 사용법 (0) | 2023.04.14 |
jib란? (0) | 2023.04.04 |
java record 개념 및 사용법 (0) | 2023.03.23 |
댓글