본문 바로가기
Dopamingo(연애 커뮤니티) 프로젝트/프로젝트

3.2 Docker Container 환경 구축

by 앙팡공기팡 2024. 12. 17.

지난글:

https://cooookieeee.tistory.com/46

 

서버는 AWS 인스턴스를 할당받아 SSH를 통해 서버에 접속에 성공했다.

다음은 서버를 웹 서버,웹어플리케이션 서버,DB 서버로 나누어 분리 배포하기 위해 Docker를 사용했다.

 

Docker를 사용한 이유:

 

- 추후 Docker Swarm을 통해 인스턴스(Worker Node) 추가 간편화

- 빠른 배포

- 서비스 연속성 보장( One Service - Many Container )

- 컴퓨터 자원 효율적 사용

 

 

[Docker 환경 구축]

 

목적: 상기와 같음

 

-1. Docker install

sudo apt update
sudo apt install -y docker.io
sudo systemctl start docker
sudo systemctl enable docker

 

-2. Docker compose install

 

sudo curl -L "https://github.com/docker/compose/releases/download/1.28.5/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
docker-compose --version

 

 

 

 

 

[Docker Compose.yml, nginx.conf, Dockerfile 작성]

 

 

 

 

 

목적: nginx - springboot -db 서버 형식으로 배포하기 위함

 

방법:

 

- 1. Docker Compose.yml (컨테이너 서비스와 볼륨,네트워크에 대한 총괄 설정 )

version: '3.8'
services:
  nginx: #nginx 관련하여 컨테이너 설정
    image: nginx:latest #nginx 이미지
    container_name: nginx_container # 비필수
    ports:
      - "80:80" # 호스트의 포트와 컨테이너의 포트포워딩
    volumes:
      - /home/ubuntu/my_project/nginx/nginx.conf:/etc/nginx/nginx.conf:ro # Bind volume 형식으로 호스트의 nginx.conf와 컨테이너 nginx.conf를 mount
    depends_on:
      - springboot # springboot 컨테이너 서비스가 먼저 만들어지고 생성
    networks:		#사용할 네트워크 지정
      - starbucks_network_02 # 네트워크를 통해 컨테이너끼리 소통 

  springboot:
    image: my-springboot_v2:latest  # Dockerfile를 기반으로 이미지 생성
    container_name: springboot_container 
    stdin_open: true  # -i 옵션 활성화 
    tty: true         # -t 옵션 활성화
    command: /bin/bash # 기본 명령어
    ports:  
      - "8080:8080" # 포트 개방
    volumes:
      - /home/ubuntu/my_project/env.properties:/app/be/env.properties # Bind volume (계정 정보 파일)
      - /home/ubuntu/my_project/shell2:/app/be/shell2 # Bind volume (CI/CD를 위해 테스트용)
    environment:
      - SPRING_PROFILES_ACTIVE=prod  # Spring Boot 프로파일 설정
    depends_on:
      - db # 생성 순서 지정
    networks:
      - starbucks_network_02

  db:
    image: mysql:8.0 #DB 이미지(Mysql)
    container_name: mysql_container
    restart: always: 컨테이너에 문제가 생겼을 시 재시작
    environment:
     MYSQL_ROOT_PASSWORD_FILE: /run/secrets/ROOT_PASSWORD #도커 시크릿 경로
     MYSQL_DATABASE_FILE: /run/secrets/DATABASE
     MYSQL_USER_FILE: /run/secrets/USERNAME
     MYSQL_PASSWORD_FILE: /run/secrets/PASSWORD
    secrets:
     - ROOT_PASSWORD # 사용할 도커 시크릿
     - DATABASE
     - USERNAME
     - PASSWORD
    ports:
      - "3306:3306" # 포트 개방
    volumes:
      - db_data:/var/lib/mysql # db_data라는 도커 볼륨을 통해 컨테이너가 삭제되도 DB 정보가 남아있게 설정
    networks:
      - starbucks_network_02

volumes: #볼륨 설정
  db_data:
  
secrets: #도커 시크릿 설정
  ROOT_PASSWORD:
    external: true #외부 
  DATABASE:
    external: true
  USERNAME:
    external: true
  PASSWORD:
    external: true

   
networks:
  starbucks_network_02:
    driver: overlay #오버레이 형식으로 네트워크 구성

 

-2.nginx.conf (nginx 웹 서버 설정) 

 

events {
  worker_connections 1024; 
}

http {
  server {
    listen 80; # 80 포트로 들어오는 inbound 처리
    location / {
      proxy_pass http://springboot:8080; # inbound를 프록시 형태로 전달 이때 DNS는 도커 DNS로 서비스이름
      proxy_set_header Host $host; #헤더 설정
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
  }
}

 

 

-3. Dockerfile( 스프링부트 이미지 생성)

 

-호스트에서 미리 빌드 시 (빠른 container 생성)

# 호스트에 빌드 후 도커에 jar 파일만 전달 시#

FROM eclipse-temurin:17-jre # jar 파일을 실행시킬 환경 image 사용
WORKDIR /app/be # 디렉토리 변경
COPY  app/be/build/libs/be-0.0.1-SNAPSHOT.jar . #호스트에 있는 jar 파일 현재 workdir에 전달
#CMD ["bash", "-c", "tail -f /dev/null"] # 잘 전달됐는지 확인하기 위해 컨테이너 유지용 명령
ENV SPRING_PROFILES_ACTIVE=prod # 운영 환경으로 전환
EXPOSE 8080 # 8080 포트로 들어올 시 서비스를 제공할 수 있도록 설정
ENTRYPOINT ["java", "-jar", "be-0.0.1-SNAPSHOT.jar"] # jar파일 실행 (서비스 실행)

 

-컨테이너에서 직접 빌드 시 

# 베이스 이미지 (빌드 단계)
FROM eclipse-temurin:17-jdk AS builder # build하기 위한 환경 구축
WORKDIR /app #workdirectory 변경
RUN apt-get update && apt-get install -y git && apt-get clean #git 설치
RUN git clone https://github.com/dopamingu/be.git # 프로젝트 클론
WORKDIR /app/be  #workdirectory 변경
RUN chmod +x ./gradlew #build 파일에 접근할 수 있도록 허용
RUN ./gradlew build -x test #build 진행

# 런타임 이미지
FROM eclipse-temurin:17-jre #런타임용 가벼운 환경으로 전환(jar파일 실행용)
WORKDIR /app #workdirectory 변경
COPY --from=build /app/build/libs/*.jar app.jar #build한 jar파일을 컨테이너의 app.jar로 옮김 
ENV SPRING_PROFILES_ACTIVE=prod # 운영 환경으로 전환
EXPOSE 8080 # 8080포트로 들어올 시 서비스 제공
ENTRYPOINT ["java", "-jar", "app.jar"] # 서비스 실행

 

 

 

 

 

[Docker Image build]

 

 

 

 

목적: Dockerfile의 설정대로 컨테이너가 생성될 수 있게 이미지를 빌드한다.

 

방법:

 

1.Dockerfile이 위치한 디렉터리로 이동

 

2.Build 명령어 실행

docker build -t <이미지 이름>:<태그> .

 

3.Docker Image가 잘 생성되었는지 확인

 

sudo docker images

 

 

 

[Docker compose로 도커 서비스 생성]

 

목적: 기존에 작성했던 docker-compose.yml 파일을 토대로 서비스를 생성한다.

 

방법:

 

1. docker-compose.yml이 있는 directory로 이동

 

 

2. Docker  compose 명령어를 통해 컨테이너 및 기타 자원들 생성

docker-compose up -d

 

 

3. Docker ps를 통해 서비스가 잘 생성 및 구동되는지 파악

sudo docker ps

 

 

 

 

 

 

 

 

 

 

 

 

이슈 트러블 슈팅:

 

1. JPA Hibernate가 연결 안되는 이슈

 

    - 원인:  1. application-prod.yml에서 jpa 구문을 추가 하지 않았음

                 2. application-prod.yml에서 jpa 구문을 추가 시 indent를 지키지 않았음

 

     - 해결방법:

                 1. DB server 생성 후 env.properties의 정보들이 환경변수로 지정되어 있는지 확인( 잘 적용되어 있었음 )

                 2. 정상적인 application-prod.yml 파일로 변경 (jpa section 추가 및 spring.config 하위로 indent 처리)

spring:
  config:
    import:
      file:env.properties
    activate:
      on-profile: prod

  datasource:
    url: jdbc:mysql://${MYSQL_HOST}:3306/${MYSQL_DB_NAME}
    username: ${MYSQL_USERNAME}
    password: ${MYSQL_PASSWORD}
    driver-class-name: com.mysql.cj.jdbc.Driver

  jpa:
    hibernate:
      ddl-auto: update
    properties:
      hibernate:
        format_sql: true
        show_sql: true
        dialect: org.hibernate.dialect.MySQL8Dialect


logging:
  level:
    root: WARN

 

 

2. Docker Image가 생성 안되는 이슈

    - 원인:  스토리지 공간 부족

 

    - 해결방법: EBS 용량 최대로 증가(프리티어시 30GB)

 

3. Dockerfile에서 directory를 찾을 수 없는 이슈

 

    - 원인: COPY --from=build /app/build/libs/*.jar app.jar 구문에서  " *.jar "로 설정 시 찾을 수가 없음 정확한 파일명 입력 

               

    - 해결방법:  직접 생성된 jar 파일 명 입력 및 실행

COPY  app/be/build/libs/be-0.0.1-SNAPSHOT.jar .
ENTRYPOINT ["java", "-jar", "be-0.0.1-SNAPSHOT.jar"]

 

4. 호스트 환경에서 빌드가 안되는 이슈

 

    - 원인:  1.gradle이 env.properties를 찾지 못해서 빌드가 안됨, gradle 자체를 찾아오지 못함

                2.javac(compiler)를 찾지 못하는 이슈

 

     - 해결방법: 1.application-prod의 spring.config.import 부분이 " file:properties "로 되어있는데,

                       경로가 잘 못 되어서 찾지 못하는 거였음 - build하는 현재 경로 기준으로 파일 배치

                        2. open jdk 17 재설치

 

 

 

참조:

-Docker composer 다운: https://zzom.co.kr/182