로컬 환경이 아닌 별도의 가상환경을 구성하는 방법이었던 하이퍼바이저를 사용하여 그 위에 게스트 OS를 올리는 방식의 단점을 개선하면서 등장하게된 프로세스 가상화 방식으로 docker는 별도의 게스트 OS 없이 docker 엔진 위에 가상환경 구동에 필요한 라이브러리와 실행파일만 가지고 있어 기존 방식보다 향상된 성능을 가진 것이 특징이다.
도커 이미지는 가상 환경이 구성되기 위한 실행 파일과 라이브러리를 가진 것으로 docker hub에서 미리 정의되어 있는 이미지를 가져와서 사용하거나 직접 DockerFile을 작성하여 생성한 이미지를 docker hub에 업로드하는 것이 가능하다.
도커 컨테이너는 정의된 도커 이미지를 바탕으로 실제 메모리가 할당되어 가상환경이 실행하고 있는 상태로 이미지와 컨테이너의 관계는 프로그램과 프로세스의 관계와 유사하다.
하나의 프로젝트를 구동하기 위해 여러가지 가상환경(JDK 컨테이너, MySQL 컨테이너, Redis 컨테이너)이 필요할 때 사용하게 되는 명령어로 docker-compose.yaml에 기록한 각 컨테이너의 이미지와 환경설정 정보를 바탕으로 여러 컨테이너를 구동할 수 있게 한다.
version: "3.7"
services:
web:
build:
context: .
dockerfile: ./Dockerfile
ports:
- "6000:5000"
container_name: flask
volumes:
- .:/app
working_dir: /app
command: >
bash -c "pip install pandas numpy flask tensorflow nltk konlpy && python server.py"
restart: always
로컬 환경의 포트와 컨테이너 내부의 포트를 서로 연결시켜주는 포트포워딩 작업으로
"로컬포트":"컨테이너포트"
를 작성하게 되면 로컬 포트로 들어오게 되는 작업이 연결된 컨테이너로 전달될 수 있게 된다.
로컬 환경의 디렉터리와 컨테이너 내부의 디렉터리를 마운트하는 설정으로 로컬 디렉터리:컨테이너 내부 디렉터리
로 작성하게 되면 로컬 디렉터리 환경을 컨테이너도 접근할 수 있게 한다.
컨테이너가 구동을 실행하게 되면 동작시킬 수 있는 명령어 모음을 설정할 수 있다.
컨테이너가 구동을 실행하기 전에 먼저 구동되어야 되는 컨테이너를 설정할 수 있다.
로컬 환경에서 스프링 프로젝트 구동에 필요한 컨테이너 환경 구성은 다음과 같이 구성할 수 있다. 실제 프로젝트에서 작성한 docker-compose.yml으로 로컬 환경과 다르게 스프링 프로젝트 구동 환경도 별도의 컨테이너로 띄워진 상태라면 application.yaml에 설정한 컨테이너 데이터베이스 연결 주소를 localhost:3306
이 아닌 컨테이너이름:컨테이너포트
로 해야 된다.
version: "3.7"
services:
web1:
image: openjdk:11
ports:
- "8080:8080"
volumes:
- .:/app
working_dir: /app
command: >
bash -c "./gradlew build && ./gradlew bootRun"
restart: on-failure
container_name: web1
depends_on:
- db
- web2
web2:
build:
context: .
dockerfile: ./flask/Dockerfile
ports:
- "6000:5000"
container_name: web2
volumes:
- ./flask:/app
working_dir: /app
command: >
bash -c "pip install pandas numpy flask tensorflow nltk konlpy && python server.py"
restart: on-failure
db:
platform: linux/x86_64
image: mysql:5.7
restart: always
container_name: mysql
ports:
- "3306:3306"
environment:
- MYSQL_DATABASE=project01
- MYSQL_ROOT_PASSWORD=samho101
- TZ=Asia/Seoul
command:
- --lower_case_table_names=1
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
volumes:
- /Users/miridih/miridih/project01/mysql:/var/lib/mysql
docker는 배포 환경에서도 동일한 환경을 가져다가 세팅할 수 있는 장점을 가지고 있기 때문에 CI/CD에서도 많이 사용되고 있는데 그 과정은 다음과 같다.
서버에서 구동되는 container 환경을 docker-compose.yml에 설정한다. Github actions를 사용해서 빌드가 된 jar를 서버의 컨테이너 환경에서 구동만 시키게 하는 것을 목적으로 수정하고 컨테이너와 마운팅한 볼륨도 서버 디렉터리 환경으로 반영한다.
version: "3.7"
services:
web1:
image: openjdk:11
ports:
- "8080:8080"
volumes:
- .:/app
working_dir: /app
command: >
bash -c "nohup java -jar build/libs/project01-0.0.1-SNAPSHOT.jar"
restart: always
container_name: web1
depends_on:
- db
- web2
web2:
build:
context: .
dockerfile: ./flask/Dockerfile
ports:
- "6000:5000"
container_name: web2
volumes:
- ./flask:/app
working_dir: /app
command: >
bash -c "pip install pandas numpy flask tensorflow nltk konlpy && python server.py"
restart: on-failure
db:
platform: linux/x86_64
image: mysql:5.7
restart: always
container_name: mysql
ports:
- "3306:3306"
environment:
- MYSQL_DATABASE=project01
- MYSQL_ROOT_PASSWORD=samho101
- TZ=Asia/Seoul
command:
- --lower_case_table_names=1
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
volumes:
- /home/ubuntu/project01/mysql:/var/lib/mysql
Github에 push가 되면 파일을 빌드하고 빌드된 프로젝트를 ssh를 통해 서버에 복사해서 옮긴 후 docker-container를 구동할 수 있도록 Github actions workflows를 작성한다.
name: CI/CD using Docker
on: [push]
jobs:
build:
name: CI/CD
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@master
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
- name: Execution permission for gradlew
run: chmod +x gradlew
shell: bash
- name: Build with Gradle
run: ./gradlew build
shell: bash
- name: create remote directory
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
script: mkdir -p /home/ubuntu/project01
- name: copy file via ssh password
uses: appleboy/scp-action@master
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
port: ${{ secrets.PORT }}
source: "."
target: "/home/ubuntu/project01"
- name: executing remote ssh commands using password
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
script: |
sh chmod +x /home/ubuntu/project01/deploy.sh
sh /home/ubuntu/project01/deploy.sh
docker-compose
docker를 활용한 CI/CD 1
docker를 활용한 CI/CD 2
도커를 활용한 CI/CD 프로젝트 예시