도커 사용이유
- CI/CD에서 지속적인 통합 과정의 테스트에서 Docker를 활용함
- 어떤 서버에 올리더라도 같은 환경으로 구성된 컨테이너로 동작하기 때문에 표준화된 배포를 구성할 수 있음
- 여러 애플리케이션의 독립성과 확장성이 높아짐
- Docker가 가상화에서 사실상 표준의 위치
# docker for mac
brew install docker docker-compose
# docker version 확인
docer --version
# 실행확인
docker info
도커 container 실행
도커의 container는 설계도 (image)를 기반으로 실행되는 실행환경을 의미함
# 도커의 image란 컨테이너의 "설계도"역할을 의미함
docker image pull nginx:1.25.3-alpine
# images 목록
docker images
docker image history nginx:1.25.3-alpine
# container 실행 명령어
docker run -d -p 8001:80 --name webserver01 nginx:1.25.3-alpine
# container 실행 확인 명령어
docker ps | grep webserver01
docker port webserver01
curl localhost:8001
# Docker 이미지 구조 확인 (json 형태로)
docker image inspect
docker image history
docker pull ubuntu:22.04
docker images
# docker create는 실제 실행하지 않고 컨테이너 생성만
docker create -ti --name ubuntu2204test ubuntu:22.04
# 모든 컨테이너가 보이는 명령어
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2ccc1b2a1144 ubuntu:22.04 "/bin/bash" 4 seconds ago Created
# container 실행 방법 1
docker start ubuntu2204test
Ubuntu2204test
docker attach ubuntu2204test
# container 실행 방법 2
# docker run 은 create/start/attach 를 순차적으로 한 번에 실행하는 것과 같음
docker run -ti --name=ubuntu2204test2 ubuntu:22.04 /bin/bash
root@57a1a1c759b6:/#
# 실행 중인 container를 확인하려면?
ps -ef | grep ubuntu2204test3
user 9710 7637 0 17:17 pts/4 00:00:00 docker run -ti --name=ubuntu2204test3 ubuntu:22.04 /bin/bash
user 9921 9377 0 17:17 pts/5 00:00:00 grep --color=auto ubuntu2204test3
docker run 자주 사용하는 옵션
-d : detached mode : 백그라운드 모드
-p : 호스트와 컨테이너의 포트를 연결 (포워딩)
-v : 호스트와 컨테이너의 디렉토리를 연결 (마운트)
-e : 컨테이너 내에서 사용할 환경변수 설정
-name : 컨테이너 이름 설정
-rm : 프로세스 종료 시 컨테이너 자동 삭제
-ti : -i와 -t를 동시에 사용한 것으로 터미널 입력을 위한 옵션
컨테이너 명령 테스트
cd ~
mkdir nodejsapp
cd nodejsapp
vi app.js # 테스트용 nodejs 앱
vi Dockerfile # 새로운 도커 이미지를 위한 Dockerfile
docker buildx build -t node-test:1.0 . # 1.0 태그를 추가하여 node-test라는 이미지를 빌드
docker images | grep node-test # 빌드 완료한 이미지 보기
docker image history node-test:1.0 # 1.0으로 태그 추가한 이미지의 Dockerfile history
docker run -itd -p 6060:6060 --name=node-test -h node-test node-test:1.0
docker ps | grep node-test
curl http://localhost:6060
실행 중인 Container에 대한 정보
# 컨테이너에서 실행 중인 프로세스 조회
docker top node-test
UID PID PPID C STIME TTY TIME CMD
root 2398 2378 0 08:37 ? 00:00:00 /sbin/tini -- node runapp.js
root 2421 2398 0 08:37 ? 00:00:00 node runapp.js
# 컨테이너에 매핑된 포트 조회
docker port node-test
8080/tcp -> 0.0.0.0:8080
# 컨테이너 리소스 통계 출력 (1회)
docker stats node-test --no-stream
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
14c475f7ac09 node-test 0.01% 9.035MiB / 15.45GiB 0.06% 1.5kB / 518B 0B / 0B 11
# 컨테이너 리소스 통계 출력 (스트림)
docker stats node-test
docker logs
# 표준 출력(stdout), 표준에러(stderr) 출력
docker logs node-test
…
# 로그를 계속 출력
docker logs –f node-test
…
…
# 출력된 로그는 파일로 관리되기 때문에 HostOS 의 disk 를 사용
docker info | grep -i log
컨테이너 내부 확인
# 컨테이너 내부 확인
docker inspect node-test
[
{
"Id": "2ccc1b2a114495e2d0b67f84e55c9c21e79c6bfff6355ae1fc2caa5225698bba",
"Created": "2023-10-29T08:04:36.295616146Z",
"Path": "/bin/bash",
"Args": [],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 1814,
"ExitCode": 0,
"Error": "",
"StartedAt": "2023-10-29T08:05:15.974255879Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:e4c58958181a5925816faa528ce959e487632f4cfd192f8132f71b32df2744b4",
"ResolvConfPath": "/var/lib/docker/containers/2ccc1b2a114495e2d0b67f84e55c9c21e79c6bfff6355ae1fc2caa5225698bba/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/2ccc1b2a114495e2d0b67f84e55c9c21e79c6bfff6355ae1fc2caa5225698bba/hostname",
docker container 정리
# 중지된 컨테이너를 포함하여 모든 컨테이너 리스트
docker container ls -a
# 태그가 붙지 않은 (dangling) 모든 이미지 삭제
docker image prune
# 남아 있는 이미지 리스트 확인 - 실행 중인 컨테이너의 이미지 등
docker image ls
# 사용하지 않는 도커 이미지, 컨테이너, 볼륨, 네트워크 등 모든 도커 리소스를 일괄적으로 삭제
docker system prune
Github Actions는 Github에 내장된 CI/CD 도구
Github Actions 동작 방법
Github Actions에서 CI란
Github Actions의 CI
예시 코드 (YAML)
# Actions 이름 github 페이지에서 볼 수 있다.
name: Run Test
# Event Trigger 특정 액션 (Push, Pull_Request)등이 명시한 Branch에서 일어나면 동작을 수행한다.
on:
push:
# 배열로 여러 브랜치를 넣을 수 있다.
branches: [ develop, feature/* ]
# github pull request 생성시
pull_request:
branches:
- develop # -로 여러 브랜치를 명시하는 것도 가능
# 실제 어떤 작업을 실행할지에 대한 명시
jobs:
build:
# 스크립트 실행 환경 (OS)
# 배열로 선언시 개수 만큼 반복해서 실행한다. ( 예제 : 1번 실행)
runs-on: [ ubuntu-latest ]
# 실제 실행 스크립트
steps:
# uses는 github actions에서 제공하는 플러그인을 실행.(git checkout 실행)
- name: checkout
uses: actions/checkout@v4
# with은 plugin 파라미터 입니다. (java 17버전 셋업)
- name: java setup
uses: actions/setup-java@v2
with:
distribution: 'adopt' # See 'Supported distributions' for available options
java-version: '17'
- name: make executable gradlew
run: chmod +x ./gradlew
# run은 사용자 지정 스크립트 실행
- name: run unittest
run: |
./gradlew clean test
Github Actions의 CD란?
main 브랜치에 코드가 통합된 경우 운영 환경에 빠르게 배포할 수 있게 함
예시 코드
name: 'CD'
on:
push:
branches: [ main ]
jobs:
cd:
runs-on: [ ubuntu-latest ]
# main 브랜치에 merge된 경우, gradle test를 실행
# main 브랜치의 코드 기준으로 jar 파일을 생성
# 생성된 jar 파일을 특정 환경 (AWS, GCP 등)에 배포
steps:
- name: checkout
uses: actions/checkout@v4
- name: java setup
uses: actions/setup-java@v3
with:
distribution: 'adopt' # See 'Supported distributions' for available options
java-version: '17'
- name: run unittest
run: |
./gradlew clean test
- name: deploy to heroku
uses: akhileshns/heroku-deploy@v3.12.12
with:
heroku_api_key: ${{secrets.HEROKU_API_KEY}}
heroku_app_name: "sampleapp-github-actions" #Must be unique in Heroku
heroku_email: "nbcdocker@proton.me"

배포까지 하려면? (cloudtype이용)
1. github settings (내 계정) 의 Developer Settings tokens의 token 생성 (generate new token)
CloudType에서 API key 설정, 깃허브 레포지포리 연결
깃허브 레포지토리에 workflows의 yml 파일에 프로젝트, 레포명 입력
자 다시 Docker
Dockerfile은 컴퓨터에서 돌아가는 앱을 만들기 위한 레시피 같은 것임.
이 레시피대로하면 Docker 이미지를 만들 수 있음
Docker 이미지는 앱을 실행하는 데 필요한 모든 것을 담고 있음
왜 사용함?
형싱은 아래와 같은데
아래 파일은 Ubuntu 최신 버전을 기반으로 Nginx를 설치하고, index.html 파일을 Nginx의 HTML 디렉터리에 복사하는 예시임
FROM ubuntu:latest
MAINTAINER Your Name <your-email@example.com>
RUN apt-get update && apt-get install -y nginx
COPY index.html /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Docker 이미지를 생성하려면 Docker CLI를 사용하여 아래와 같은 명령을 실행함
docker buildx build -t my-nginx:latest .
docker build -t my-nginx:latest . # 위 명령이 실행되지 않는 경우 실행
컨테이너 실행하는 명령어
docker run -d -p 80:80 my-nginx:latest
컨테이너 종료하는 명령어
docker stop my-nginx
Docker 파일로 FastAPI 앱을 실행하는 예제
FROM python:3.11
RUN pip install pipenv
WORKDIR /app
ADD . /app/
RUN pipenv --python 3.11
RUN pipenv run pip install poetry
RUN pipenv sync
RUN pipenv run pip install certifi
ARG STAGE
RUN sh -c 'echo "STAGE=$STAGE" > .env'
RUN sh -c 'echo "PYTHONPATH=." >> .env'
RUN chmod +x ./scripts/run.sh
RUN chmod +x ./scripts/run-worker.sh
CMD ["./scripts/run.sh"]
nginx 이미지를 생성하는 예제 (nginx:latest와 동일)
# Dockerfile
FROM ubuntu:22.04
MAINTAINER your-name <your-email@example.com>
LABEL purpose=Web Server
# nginx 패키지 설치
RUN apt-get update && apt-get install -y nginx
# nginx 설정 파일 복사
COPY nginx.conf /etc/nginx/nginx.conf
# Nginx 실행
CMD ["nginx", "-g", "daemon off;"]
nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
gzip on;
gzip_disable "msie6";
include /etc/nginx/conf.d/*.conf;
}
각 애플리케이션의 Dockerfile 작성
docker-compose-yaml 파일 작성
내가 만든 애플리케이션을 실행하기 위해 필요한 database라든지 redis라든지 다른 서비스들을 한꺼번에 정의하는 파일을 작성
docker compose up 으로 실행