olrlobt
[INFRA] Docker와 Dockerfile, Docker-compose 구성하기 본문
2024.02.20 - [Infra] - [INFRA] Nginx를 사용하여 HTTPS 요청 처리하기
Docker
Docker는 소프트웨어 개발 분야에서 광범위하게 사용되는 오픈 소스 컨테이너화 플랫폼이다. 도커 컨테이너는 일종의 소프트웨어를 소프트웨어의 실행에 필요한 모든 것을 포함하는 완전한 파일 시스템 안에 감싼다. 여기에는 코드, 런타임, 시스템 도구, 시스템 라이브러리 등 서버에 설치되는 무엇이든 아우른다. 이는 실행 중인 환경에 관계없이 언제나 동일하게 실행될 것을 보증한다.
Docker 이미지는 애플리케이션을 실행하는 데 필요한 모든 것을 포함하는 경량의, 독립적인, 실행 가능한 소프트웨어 패키지로, 컨테이너를 생성하는 데 사용된다.
Docker 설치
먼저 Docker를 설치하기 전에, Docker의 공식 GPG 키를 시스템의 패키지에 추가해야 한다. GPG 키를 시스템 패키지에 추가하게 되면, 패키지의 내용을 기반으로 한 해쉬 값이 생성되게 되는데, 만약 패키지가 수정되게 되면 시스템 패키지의 해시 값이 변하게 되면서 원본과 일치하지 않게 된다.
이와 같은 방식을 이용하여 GPG 키를 통해 패키지가 신뢰할 수 있는 기관에서 생성되었음을 확인할 수 있다. 또한, GPG 서명은 패키지가 배포된 이후로 수정되지 않았음을 보증한다.
필요한 패키지 설치
HTTPS를 통해 저장소에서 패키지를 안전하게 다운로드하고, Docker의 공식 GPG 키를 추가하기 위해 필요한 패키지를 다운로드한다.
$ sudo apt-get update
$ sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
software-properties-common
Docker의 공식 GPG 키 추가
Docker 저장소의 패키지가 신뢰할 수 있는 출처인지 확인하기 위해 Docker의 공식 GPG 키를 시스템에 추가한다.
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
Docker의 공식 저장소를 시스템의 APT 소스 목록에 추가
$ sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
패키지 목록 업데이트 및 Docker 설치
새로 추가된 Docker 저장소의 패키지 정보를 포함하여 시스템의 전체 패키지 목록을 업데이트하고, Docker CE를 설치한다.
$ sudo apt-get update
$ sudo apt-get install docker-ce
사용자를 Docker 그룹에 추가
$ sudo usermod -aG docker ${USER}
이 명령어를 통해 사용자는 sudo 명령어 없이 Docker 명령을 사용할 수 있게 된다.
해당 명령어를 정상적으로 적용하기 위해서는 EC2에 재접속 해야한다.
Docker 서비스 시작 및 자동 시작 설정
$ sudo systemctl start docker
$ sudo systemctl enable docker
Docker 버전 확인
$ docker --version
위와 같이 나온다면 설치가 잘 완료된 것이다.
Dockerfile
Dockerfile은 Docker 이미지를 생성하기 위한 명령어와 설정을 포함하는 텍스트 파일이다. 이 파일은 Docker 이미지를 빌드할 때 필요한 모든 지시사항을 담고 있다. Dockerfile을 사용하면 애플리케이션과 그 의존성을 포함하는 컨테이너화된 환경을 정의, 생성, 자동화할 수 있다.
Dockerfile은 첫 글자는 대문자로 "Dockerfile"이라는 이름의 텍스트 파일로 생성하며, 대부분 프로젝트의 루트 경로에 위치시킨다.
프로젝트 루트 디렉토리/
├── src/
│ ├── main/
│ │ ├── java/
│ │ └── resources/
│ └── test/
├── build.gradle # Gradle 빌드 스크립트
├── settings.gradle
└── Dockerfile # Dockerfile 위치
Dockerfile의 기본 구조
Spring의 경우 아래와 같이 Dockerfile을 구성할 수 있다.
FROM openjdk:17-jdk # 베이스 이미지로 OpenJDK가 포함된 이미지 사용
WORKDIR /app # 현재 디렉토리 설정
# 애플리케이션의 JAR 파일을 컨테이너에 app.jar라는 이름으로 복사
# 실제 build된 jar 파일 경로와 build.gradle을 참고하여 파일 이름을 작성해 주어야 한다
COPY build/libs/bid-admin-0.0.1-SNAPSHOT.jar app.jar
EXPOSE 8080 # 포트 8080 열기
ENTRYPOINT ["java","-jar","app.jar"] # 애플리케이션 실행
- FROM:
이미지의 기반이 되는 베이스 이미지를 지정한다. 예를 들어, FROM ubuntu:18.04은 Ubuntu 18.04를 베이스 이미지로 사용한다. - WORKDIR:
명령어를 실행할 작업 디렉터리를 설정한다. - RUN:
이미지를 빌드하는 동안 명령어를 실행한다. 예를 들어, 패키지를 설치할 때 사용할 수 있다. - CMD:
컨테이너가 시작될 때 실행할 명령어를 지정한다. Dockerfile에는 하나의 CMD만 있어야 한다. - COPY:
호스트 시스템의 파일이나 디렉터리를 이미지의 파일 시스템으로 복사한다. - ADD:
COPY와 비슷하지만, 리모트 URL에서 파일을 추가하거나 압축 파일을 자동으로 압축 해제할 수 있다. - EXPOSE:
컨테이너에서 리슨 할 포트를 지정한다. 하지만 실제 포트 오픈을 강제하지 않으며, 문서화 목적으로만 사용된다. - ENTRYPOINT:
컨테이너가 시작될 때 실행할 스크립트나 명령어를 지정한다. CMD와 함께 사용되어, 실행 파일과 파라미터를 분리할 수 있다. - ENV:
환경 변수를 설정한다.
여기서 중요한 점은 COPY 명령어가 사용하는 경로이다. Gradle을 사용할 때, 빌드 결과물은 보통 build/libs디렉터리에 위치한다. 따라서 Dockerfile에서는 이 디렉터리 내 생성된 JAR 파일을 컨테이너 내부로 복사하도록 지정한다.
$ docker build -t spring-boot-app .
docker build :
Docker 이미지를 빌드하기 위한 명령어이다.
-t : 이미지의 이름과 태그를 지정한다.
여기서 spring-boot-app은 생성할 이미지의 이름과 태그를 지정하는 것이며, 마지막의 점(. )은 현재 디렉터리를 가리키며, Dockerfile 위치를 의미한다.
$ docker run -d -p 8080:8080 spring-boot-app
docker run : Docker 이미지로부터 컨테이너를 실행한다.
-d : 컨테이너를 백그라운드에서 실행한다.
-p 8080:8080 : 호스트의 8080 포트와 컨테이너의 8080 포트를 연결한다.
이렇게 하면 호스트의 8080 포트를 통해 컨테이너의 8080 포트로 연결되며, 해당 컨테이너에 접근이 가능해진다.
Dockerfile은 사용하는 프레임워크나, 기술에 따라 구성이 달라질 수 있다.
예를 들어, 정적 파일로 빌드가 되는 React 같은 경우는 Dockerfile에서 Nginx를 통해 컨테이너 내부의 정적 파일을 서빙해 주어야 한다.
FROM node:14 as build-stage # Node.js 이미지를 베이스 이미지로 사용
WORKDIR /app # 작업 디렉토리 설정
COPY package*.json ./ # 애플리케이션의 package.json과 package-lock.json을 이미지로 복사
RUN npm install # 의존성 설치
COPY . . # 애플리케이션의 소스 코드를 이미지로 복사
RUN npm run build # React 애플리케이션 빌드
FROM nginx:alpine as production-stage # Nginx 이미지를 베이스 이미지로 사용
COPY --from=build-stage /app/build /usr/share/nginx/html # 빌드 단계에서 생성된 빌드 파일을 Nginx의 서빙 디렉토리로 복사
EXPOSE 80 # 기본 포트로 80을 노출
CMD ["nginx", "-g", "daemon off;"] # Nginx 실행
위와 같이 Dockerfile을 구성하고,
$ docker build -t react-app .
$ docker run -d -p 8080:80 react-app
도커 이미지를 만들어 컨테이너로 실행시켜 주면, 호스트의 8080 포트로 Nginx가 서빙해 준 React의 정적 파일에 접근이 가능해진다.
Docker compose
Docker Compose는 여러 Docker 컨테이너를 정의하고 실행하기 위한 도구이다. YAML 파일(docker-compose.yml)을 사용하여 애플리케이션의 서비스, 네트워크, 볼륨 등을 구성할 수 있다. Docker Compose는 특히 멀티 컨테이너 Docker 애플리케이션 개발, 테스팅, 배포에 유용하다.
Docker-compose 설치
아래 명령어로 리눅스 환경에서 Docker compose를 설치할 수 있다.
$ sudo apt-get install docker-compose
잘 설치가 되었다면 아래와 같이 확인할 수 있다.
$ docker-compose --version
docker-compose.yml 파일 기본 구조
Docker compose 파일은 docker-compose.yml이라는 이름으로 프로젝트 루트 경로에 위치시킨다.
my-spring-boot-app/
├── src/
│ └── main/
│ ├── java/
│ └── resources/
├── Dockerfile
├── docker-compose.yml # docker-compose.yml 위치
├── build.gradle # Gradle 빌드 스크립트
├── settings.gradle
└── .gitignore
docker-compose.yml은 아래와 같이 구성된다.
version: '3'
services:
web:
image: example/mywebapp:latest
ports:
- "5000:5000"
depends_on:
- db
db:
image: postgres:latest
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
version : Docker Compose API의 버전을 나타낸다. Docker Compose 버전은 도커 엔진 버전에 의존성이 있기 때문에 가능하면 최신 버전을 사용하는 것이 좋다.
services: 컨테이너화된 애플리케이션의 각 컴포넌트를 정의한다. 이 예제에서는 web과 db 두 개의 서비스가 있다.
web: 사용자 정의 웹 애플리케이션 서비스다. 이 서비스는 example/mywebapp:latest라는 이미지를 사용하여 컨테이너를 생성한다.
- image: web 서비스에 사용될 Docker 이미지를 지정한다. 여기서는 example/mywebapp의 latest 태그를 사용하는 이미지를 사용한다.
- ports: 호스트와 컨테이너 간의 포트 매핑을 정의한다. 이 설정은 호스트의 5000 포트와 컨테이너의 5000 포트를 연결한다.
- depends_on: web 서비스가 db 서비스에 의존한다는 것을 나타낸다. 이는 db 서비스가 web 서비스보다 먼저 시작되어야 함을 의미한다.
$ docker-compose up
그리고 docker-compose.yml이 있는 경로에서 위의 명령어로 실행하면 된다.
나는 docker-compose.yml을 아래와 같이 구성하여,
프론트 React와, 백엔드 Spring boot, 웹소켓 Node Js를 한 docker-compose.yml에 작성하여 필요에 의해 한 아이템씩 빌드할 수 있도록 젠킨스 파이프라인을 구성하였다.
상세한 것은 아래 내용을 참고하면 된다.
version: '3.8'
services:
frontend:
image: olrlobt/bid-front:latest
container_name: bid-front
ports:
- "3000:443"
volumes:
- /etc/letsencrypt:/etc/letsencrypt
environment:
TZ: Asia/Seoul
bid-socket:
image: olrlobt/bid-socket:latest
container_name: bid-socket
ports:
- "3001:3001"
volumes:
- /etc/letsencrypt:/etc/letsencrypt
environment:
TZ: Asia/Seoul
bid-core:
image: olrlobt/bid-core:latest
container_name: bid-core
ports:
- "8083:8083"
volumes:
- /home/ubuntu/config/application.yml:/config/core/application.yml
- /home/ubuntu/config/application_core.yml:/config/core/application-port.yml
environment:
- SPRING_CONFIG_LOCATION=file:/config/core/
- SPRING_PROFILES_ACTIVE=port
- TZ=Asia/Seoul
bid-admin:
image: olrlobt/bid-admin:latest
container_name: bid-admin
depends_on:
- bid-core
ports:
- "8081:8081"
volumes:
- /home/ubuntu/config/application.yml:/config/admin/application.yml
- /home/ubuntu/config/application_admin.yml:/config/admin/application-port.yml
environment:
- SPRING_CONFIG_LOCATION=file:/config/admin/
- SPRING_PROFILES_ACTIVE=port
- TZ=Asia/Seoul
bid-student:
image: olrlobt/bid-student:latest
container_name: bid-student
depends_on:
- bid-core
ports:
- "8082:8082"
volumes:
- /home/ubuntu/config/application.yml:/config/student/application.yml
- /home/ubuntu/config/application_student.yml:/config/student/application-port.yml
environment:
- SPRING_CONFIG_LOCATION=file:/config/student/
- SPRING_PROFILES_ACTIVE=port
- TZ=Asia/Seoul
'Infra' 카테고리의 다른 글
[INFRA] Jenkins 설치하기 (0) | 2024.03.30 |
---|---|
[INFRA] AWS EC2 프리티어 인스턴스 생성하기 (2) | 2024.03.25 |
[INFRA] Docker에서 Nginx 컨테이너 실행과 https 설정하기 (1) | 2024.03.20 |
[INFRA] Nginx를 사용하여 HTTPS 요청 처리하기 (3) | 2024.02.20 |
[INFRA] EC2 서버 기본 설정과, SWAP메모리 할당하기 (1) | 2024.02.19 |