인프런

도커를 실무에 적용하기

date
May 29, 2024
slug
개발자를-위한-쉬운-도커-8
status
Public
tags
개발자를 위한 쉬운 도커
author
summary
[개발자를 위한 쉬운 도커] 강의 정리
type
Post
thumbnail
updatedAt
Jun 4, 2024 04:23 AM
category
인프런

💻 명령어


 

📝 강의 정리


[1]. 레이어 관리


💡
도커 레이어 관리 전략 및 이미지 크기를 작게 !

[1-1]. RUN 지시어는 && 을 활용해 최대한 하나로 처리하자.

  • 보편적으로 Dockerfile에 작성된 지시어 하나 당 레이어가 한 개 추가된다. → 따라서, &&을 활용해 RUN 지시어의 개수를 줄여 레이어의 개수를 최소화 하자.

[1-2]. 애플리케이션의 크기를 가능한 작게 관리하자.

[1-3]. 베이스 이미지는 가능한 작은 이미지를 사용하자 :: alpine OS

[1-4]. .dockerignore 을 통해 불필요한 파일을 제거하자

 

[2]. 캐싱을 활용한 빌드


  • Docker 는 각 단계의 결과 레이어를 캐시 처리한다.
    • → 지시어가 변경되지 않으면 다음 빌드에서 레이어를 재사용함
      ❗️COPY 지시어의 경우, COPY하는 파일의 내용까지 동일해야 캐싱됨
  • 레이어가 변경되면, 해당 레이어를 포함한 이후의 레이어는 캐시를 사용하지 않고 새로운 레이어가 만들어진다.
    • notion image
 
→ 따라서, 잘 변경되지 않는 레이어를 하단에 배치하면, 캐시를 활용하는 빈도를 높일 수 있다. ex) package.json, package-lock.json 등
notion image
 

[2-1]. 캐싱을 이용하지 않은 빌드

  • docker build 명령어에 --no-cache 옵션
    • notion image
       

[2-2]. 캐싱을 이용한 빌드

notion image
  • 빌드속도가 1.7초밖에 소요되지 않는다.
 

[2-3]. 소스코드 수정 후 빌드 확인

notion image
  • COPY 지시어 내의 소스 코드의 수정이 이루어지면, 해당 레이어부터 캐싱이 아닌 새로운 레이어를 생성해 빌드한다.

[3]. nginx 설정 커스터마이징, 3 Tier 아키텍쳐 구성


💡
Nginx의 프록시 기술을 사용해 3 Tier 아키텍쳐를 구성해보자
 

[3-1]. leafy-front

  • nginx.conf 파일 작성
    • 코드
      server { listen 80; server_name _; location / { root /usr/share/nginx/html; index index.html index.htm; } location /api/ { proxy_pass http://leafy:8080; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } }
  • api.js 변경
 
 

[4]. 환경 변수를 활용한 동적 서버 설정


server { listen 80; server_name _; location / { root /usr/share/nginx/html; index index.html index.htm; } location /api/ { proxy_pass http://leafy:8080; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } }
  • 기존 backend proxy경로가 정적으로 선언되어있다.
  • 환경 별로 Nginx가 프록시 해야하는 주소가 바뀔 경우,
    • → 해당 파일을 수정해야하고, 파일이 변경되었으므로 이미지 빌드가 필요하다.
  • 또한, 하나의 이미지로 복수의 컨테이너가 실행 중인 경우, 설정이 복잡해진다.
→ 환경 변수를 통한 동적 서버 설정으로 이러한 단점을 극복해보자 !
 

[3-1]. nginx.conf 수정

location /api/ { proxy_pass http://${BACKEND_HOST}:${BACKEND_PORT}; }
 

[3-2]. docker-entrypoint.sh 작성

#!/bin/sh set -e # default.conf.template 파일에서 환경 변수를 대체하고 결과를 default.conf에 저장 # envsubst '$VARIABLE_NAME' < input_file > output_file envsubst '${BACKEND_HOST} ${BACKEND_PORT}' < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf # 다음 명령어를 실행 exec "$@"
 

[3-3]. Dockerfile 수정

COPY nginx.conf /etc/nginx/conf.d/default.conf.template # 옵션의 기본값 ENV BACKEND_HOST leafy ENV BACKEND_PORT 8080 COPY docker-entrypoint.sh /usr/local/bin/ RUN chmod +x /usr/local/bin/docker-entrypoint.sh # 빌드 스테이지에서 생성된 빌드 결과물을 복사 COPY --from=build /app/dist /usr/share/nginx/html EXPOSE 80 ENTRYPOINT ["docker-entrypoint.sh"] CMD ["nginx", "-g", "daemon off;"]

[5]. PostgreSQL 이중화 DB 구성


💡
고가용성을 보장하는 서버 이중화를 구성해보자
  • 단일 서버 구성 시, 단일 서버에 장애가 발생하면 전체 서비스의 장애로 이어진다.
 

[5-1]. 이중화 DB 구성 방법

여러 컨테이너가 하나의 볼륨을 공유
✅  구성이 간단하다.
❌  볼륨에 문제가 생길 경우 대처가 어렵다
❌  볼륨의 성능에 부하가 생길 수 있다.
여러 컨테이너가 별도의 볼륨을 사용
✅  장애 대처가 쉽다.
✅  성능 부하가 적다.
❌  구성이 복잡하다.
❌  데이터 동기화가 필요하다.
 

[5-2]. Primary-Standby Replication

notion image
  • 프라이머리 서버에만 쓰기 작업을 수행
  • 프라이머리 서버의 상태를 스탠바이 서버에 복제
 

[5-3]. Primary-Primary Replication

notion image
  • 모든 서버에 읽기/쓰기 작업을 수행
  • 여러 서버에서 동시에 쓰기 작업이 일어나기 때문에 동기화 작업이 복잡하다.
 

[5-4]. Primary-Standby 구성화 실습

 

[6]. 컨테이너 애플리케이션 최적화


[6-1]. 컨테이너가 사용할 수 있는 리소스 사용량을 제한

docker run [option]
  • --cpus= : 컨테이너가 사용할 최대 CPU 코어 수
  • --memory= : 컨테이너가 사용할 최대 메모리 ( b, k, m, g단위 )
 

[6-2]. 컨테이너 리소스 사용량 조회

  • docker stats [컨테이너명/ID]
  • docker events : HOST OS에서 발생하는 이벤트 로그 조회
 

[6-3]. 리소스 사용량을 초과할 경우

  • CPU 사용량이 초과할 경우
    • CPU 스로틀링 발생
    • 애플리케이션의 성능 저하
  • 메모리 사용량이 초과할 경우
    • OOM( Out Of Memory ) Killer 프로세스가 실행되고 컨테이너가 강제로 종료됨
 

[6-4]. JVM 튜닝

💡
힙 메모리 영역 관리
  • 일반적으로 애플리케이션 서버 메모리의 50~70%를 할당
  • 따라서, 자바 애플리케이션의 힙 메모리양을 설정할 때는, 컨테이너의 제한량도 함께 고려해야 함.
 
JVM 튜닝 ( JAVA 10 미만 )
FROM openjdk:8-jre-alpine # JVM 튜닝을 위한 환경변수 ENV JAVA_OPTS="-XX:+UnlickExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap"
  • java 10 미만의 버전에서는 해당 환경 변수를 선언해준다.
    • ❗️ java 10 버전 이상이라도, -Xmx 옵션을 통해 힙메모리를 지정해둔 상황이라면, 해당 환경변수를 같이 추가해주어야 한다.

[7]. 컨테이너 내부에서 개발


 

[8]. JAVA 개발환경 컨테이너 활용


 
 

📎 출처