오토에버 클라우드 2기 34일차
오토에버 클라우드 2기 34일차
Docker & Kafka
1. Dockerfile 작성 가이드
Dockerfile은 Docker 이미지를 생성하기 위한 명령어들을 담고 있는 텍스트 파일 이 파일을 통해 애플리케이션 환경을 코드로 관리하고, 일관된 배포 환경을 구축할 수 있다
Dockerfile 주요 명령어
FROM
- 설명: 생성할 이미지의 바탕이 될 베이스 이미지를 지정 필수 항목이며, 보통 Dockerfile의 가장 처음에 위치
- 권장 사항: 공식 이미지를 사용하고,
slim또는alpine같이 가벼운 버전을 사용하여 최종 이미지 크기를 줄이는 것이 좋다 태그를 생략하면latest로 자동 지정되지만, 버전 관리를 위해 특정 버전 태그(ubuntu:22.04)를 명시하는 것을 강력히 권장 작성 예시:
1
FROM ubuntu:22.04
MAINTAINER (Deprecated)
- 설명: 이미지 작성자의 이름과 이메일 정보를 기입
- 참고: 이 명령어는 더 이상 권장되지 않으며,
LABEL을 사용하여 메타데이터를 관리하는 것이 좋다 - 작성 예시:
1
MAINTAINER adam <itstudy@kakao.com>
LABEL
- 설명: 이미지에 메타데이터를 추가한다 버전 정보, 설명, 라이선스 등 다양한 정보를 키-값 쌍으로 저장할 수 있다
- 작성 예시:
1 2 3
LABEL version="1.0" LABEL description="Web Service image for project X" LABEL maintainer="adam <itstudy@kakao.com>"
RUN
- 설명: 베이스 이미지 위에서 새로운 레이어를 생성하며 명령어를 실행 주로 패키지 설치, 소스코드 빌드, 디렉토리 생성 등에 사용
- 권장 사항:
- 레이어 최소화:
&&를 사용하여 여러 명령어를 한 줄의RUN으로 묶으면 이미지 레이어 수를 줄여 빌드 시간을 단축하고 이미지 크기를 최적화할 수 있다 - 캐시 정리:
apt,yum등 패키지 매니저 사용 후, 불필요한 캐시를 삭제(rm -rf /var/lib/apt/lists/*)하여 이미지 크기를 줄이는 것이 좋다
- 레이어 최소화:
- 작성 방식:
Shell 형식:
/bin/sh -c셸을 통해 명령어를 실행1 2 3 4 5
RUN apt-get update && apt-get install -y \ nginx \ git \ vim \ && rm -rf /var/lib/apt/lists/*
Exec 형식: 셸을 거치지 않고 직접 실행 파일을 호출 셸 환경 변수를 사용할 수 없다
1 2
RUN ["/bin/bash", "-c", "apt-get update"] RUN ["/bin/bash", "-c", "apt-get install -y nginx git vim"]
CMD
- 설명: 이미지를 컨테이너로 실행할 때 기본적으로 실행될 명령어를 지정한다 Dockerfile 내에 여러
CMD가 있다면 마지막CMD만 유효docker run명령어 실행 시 인자를 전달하면CMD명령어는 무시되고 해당 인자로 대체 - 주요 용도:
- 컨테이너 시작 시 애플리케이션 데몬을 실행할 때 사용
ENTRYPOINT에 파라미터를 전달하는 용도로 사용
- 작성 예시:
1 2 3 4 5 6
# Exec 형식 (권장) CMD ["apachectl", "-D", "FOREGROUND"] # ENTRYPOINT와 함께 사용 ENTRYPOINT ["/usr/bin/python3"] CMD ["app.py"]
ENTRYPOINT
- 설명:
CMD와 유사하게 컨테이너가 시작될 때 실행될 명령어를 지정하지만, 항상 실행되는 고정된 명령어라는 차이점이 있다docker run으로 인자를 전달하면ENTRYPOINT명령어에 대한 파라미터로 사용 CMD와의 조합:ENTRYPOINT로 실행 파일을 고정하고,CMD로 기본 파라미터를 지정하면 유연하게 컨테이너를 실행할 수 있다- 작성 예시:
1 2 3 4 5 6 7 8 9 10
# 스크립트 파일 실행 COPY ./entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"] # CMD와 조합 ENTRYPOINT ["python3"] CMD ["app.py", "--mode=production"] # 위와 같이 작성 후 `docker run my-image --mode=development` 실행 시 # -> python3 app.py --mode=development 가 실행됨
COPY
- 설명: 호스트 머신의 파일이나 디렉토리를 이미지 안의 지정된 경로로 복사 경로 외의 기능은 지원하지 않으며, 빌드 컨텍스트(Dockerfile이 위치한 디렉토리 및 하위 디렉토리) 내의 파일만 복사할 수 있다
- 권장 사항: 단순 파일 복사에는
ADD보다 명확하고 예측 가능한COPY사용을 권장 - 작성 예시:
1 2 3 4 5
# 호스트의 index.html 파일을 이미지의 /usr/share/nginx/html/ 경로에 복사 COPY index.html /usr/share/nginx/html/ # app 디렉토리 전체를 이미지의 /app 경로에 복사 COPY ./app /app
ADD
설명:
COPY와 기능이 유사하지만 추가적인 기능을 제공- URL 지원: 호스트 파일 대신 URL을 지정하면 해당 파일을 다운로드하여 이미지에 추가
- 압축 해제:
tar,tar.gz등 압축 파일을 지정하면 자동으로 압축을 해제하여 이미지에 추가
- 주의: 자동 압축 해제 등 예측하기 어려운 동작 때문에, 단순 복사에는
COPY를 사용하는 것이 좋다 - 작성 예시:
1 2 3 4 5
# URL에서 파일 다운로드 ADD [https://example.com/file.txt](https://example.com/file.txt) / # 압축 파일 추가 및 자동 해제 ADD archive.tar.gz /data/
ENV
- 설명: 이미지 내부에서 사용할 환경 변수를 설정 애플리케이션에서 필요한 설정값(DB 정보, API 주소 등)을 관리하는 데 유용하다
작성 예시:
1 2 3
ENV APP_HOME /app ENV DB_HOST database.example.com ENV PATH $APP_HOME/bin:$PATH
EXPOSE
- 설명: 컨테이너가 실행될 때 리스닝할 포트와 프로토콜을 명시적으로 선언 이 명령어는 실제 포트를 외부에 노출(Publish)하지 않으며, 어떤 포트를 사용해야 하는지에 대한 정보를 남기는 문서화 목적이 강하다 실제 포트 노출은
docker run시-p또는-P옵션으로 지정 작성 예시:
1 2
# 컨테이너가 80번 포트를 TCP 프로토콜로 리스닝함을 명시 EXPOSE 80/tcp
VOLUME
- 설명: 호스트 또는 다른 컨테이너와 데이터를 공유하거나 영속적으로 데이터를 보관하기 위해 볼륨을 마운트할 경로를 지정 로그 파일, 데이터베이스 파일 등 컨테이너가 삭제되어도 유지해야 할 데이터를 저장하는 데 사용
- 작성 예시:
1 2
# 이미지의 /var/log 디렉토리를 볼륨으로 지정 VOLUME ["/var/log"]
USER
- 설명:
RUN,CMD,ENTRYPOINT명령어를 실행할 사용자를 지정 기본 사용자는root이며, 보안을 위해 최소한의 권한을 가진 일반 사용자를 생성하여 지정하는 것이 좋다 - 작성 예시:
1 2
RUN useradd --create-home --shell /bin/bash adam USER adam
WORKDIR
- 설명:
RUN,CMD,ENTRYPOINT,COPY,ADD명령이 실행될 기본 작업 디렉토리를 설정cd명령어를 사용하는 것보다WORKDIR을 사용하는 것이 명확하고 효율적 - 작성 예시:
1 2 3 4
WORKDIR /workspace # 이후 명령어들은 /workspace 디렉토리에서 실행됨 COPY . . RUN make install
ARG
- 설명:
docker build시점에--build-arg옵션을 통해 전달할 수 있는 변수를 정의ENV와 달리 이미지 빌드 과정에서만 사용되며, 실행 중인 컨테이너에는 남아있지 않는다 (단,ENV로 다시 할당하면 남길 수 있음) - 주요 용도: 빌드 환경에 따라 다른 값을 사용하거나, 비밀키 등 민감한 정보를 이미지에 직접 저장하지 않고 빌드 시 주입할 때 사용
- 작성 예시:
1 2 3
ARG db_name=default_db # `docker build --build-arg db_name=adam_db .` 실행 시 db_name 변수에 'adam_db'가 할당됨 CMD /bin/db_start.sh -d ${db_name}
ONBUILD
- 설명: 현재 이미지를 빌드할 때는 실행되지 않고, 이 이미지를
FROM으로 사용하는 다른 이미지를 빌드할 때 실행될 명령어를 지정 - 주요 용도: 애플리케이션 프레임워크 이미지처럼, 이를 기반으로 하는 여러 애플리케이션 이미지에서 공통적으로 수행해야 할 작업을 정의할 때 유용
- 작성 예시:
1 2 3 4
# 현재 이미지를 기반으로 하는 자식 이미지 빌드 시, # 소스 코드를 /app 디렉토리로 복사하고 종속성을 설치함 ONBUILD COPY . /app ONBUILD RUN npm install
SHELL
- 설명:
RUN,CMD,ENTRYPOINT의 Shell 형식이 사용할 기본 셸을 지정 Linux의 기본값은["/bin/sh", "-c"], Windows는["cmd", "/S", "/C"] - 작성 예시:
1
SHELL ["/bin/bash", "-c"]
HEALTHCHECK
- 설명: 컨테이너 내부의 애플리케이션이 정상적으로 작동하는지 상태를 주기적으로 체크
docker ps나docker inspect를 통해 상태(starting,healthy,unhealthy)를 확인할 수 있다 - 옵션:
--interval=DURATION: 체크 간격 (기본값: 30s)--timeout=DURATION: 타임아웃 시간 (기본값: 30s)--retries=N: 실패 시 재시도 횟수 (기본값: 3)
- 상태 코드:
0: 성공 (healthy)1: 실패 (unhealthy)2: 예약됨 (사용하지 않음)
- 작성 예시:
1 2 3 4
# 1분마다 localhost로 curl 요청을 보내 3초 안에 응답이 없으면 타임아웃, # 5회 연속 실패 시 컨테이너를 unhealthy 상태로 변경 HEALTHCHECK --interval=1m --timeout=3s --retries=5 \ CMD curl -f http://localhost/ || exit 1
Dockerfile 작성 팁 및 권장사항
- 빌드 캐시 활용: Docker는 각 명령어를 레이어로 만들어 캐싱 내용이 자주 변경되는
COPY나ADD명령어는 가급적 Dockerfile의 뒷부분에 배치하여 빌드 캐시를 최대한 활용하고 빌드 속도를 높일 수 있다 - 이미지 크기 최소화:
.dockerignore파일을 사용하여 빌드에 불필요한 파일(로그, 임시 파일,node_modules등)이 이미지에 포함되지 않도록 한다- 다단계 빌드(Multi-stage builds)를 사용하여 빌드에만 필요했던 도구들(컴파일러, 빌드 라이브러리 등)을 최종 이미지에서 제거하여 이미지 크기를 획기적으로 줄일 수 있다
- 명령어 순서: 논리적으로 연관된 명령어들을 묶고, 변경 빈도가 낮은 순서대로 작성하는 것이 좋다 (예: 패키지 설치 -> 소스코드 복사 -> 빌드)
이미지 생성 명령어
1
2
3
4
5
6
7
8
# 기본 명령어 형식: docker build [옵션] <Dockerfile 경로>
docker build -t <이미지이름>:<태그> .
# 예시: 현재 디렉토리의 Dockerfile을 사용하여 my-web-app:1.0 이미지를 생성
docker build -t my-web-app:1.0 .
# 파일명이 Dockerfile이 아닌 경우 -f 옵션 사용
docker build -t my-web-app:1.0 -f Dockerfile.prod .
2. Kafka 설치 가이드 (Linux 기준)
Apache Kafka는 대용량의 실시간 로그 및 이벤트 데이터를 처리하기 위해 링크드인에서 개발한 분산 스트리밍 플랫폼 초기에는 파편화된 데이터 수집 파이프라인의 복잡성을 해결하기 위해 만들어졌다
사전 준비 사항
Kafka는 JVM(Java Virtual Machine) 위에서 동작하므로, Java(JDK)가 반드시 설치되어 있어야 한다
설치 및 설정 과정
- Java(JDK) 설치 및 확인
1 2 3 4 5 6 7 8
# 패키지 목록 업데이트 sudo apt update # OpenJDK 17 설치 (Kafka 3.x 버전은 Java 11 이상 권장) sudo apt install -y openjdk-17-jdk # 설치된 Java 버전 확인 java -version
- Kafka 다운로드 및 압축 해제
1 2 3 4 5
# 원하는 버전의 Kafka 바이너리 다운로드 (Scala 2.13, Kafka 3.6.0 예시) wget [https://archive.apache.org/dist/kafka/3.6.0/kafka_2.13-3.6.0.tgz](https://archive.apache.org/dist/kafka/3.6.0/kafka_2.13-3.6.0.tgz) # 압축 해제 tar xvf kafka_2.13-3.6.0.tgz
- Kafka 디렉토리 이동 및 환경 변수 설정
1 2 3 4 5 6 7 8 9 10 11 12
# 관리하기 용이한 경로로 디렉토리 이동 sudo mv kafka_2.13-3.6.0 /opt/kafka # 셸 설정 파일 열기 (bash 사용 시) vi ~/.bashrc # 파일 맨 아래에 다음 내용 추가 export KAFKA_HOME=/opt/kafka export PATH=$PATH:$KAFKA_HOME/bin # 변경된 환경 변수 적용 source ~/.bashrc
- Kafka 설정 (힙 메모리 및 외부 접속)
힙 메모리 설정: Kafka는 기본적으로 1GB의 힙 메모리를 사용한다 서버 사양에 따라 이 값을 조절할 수 있다
KAFKA_HEAP_OPTS환경 변수를 설정하여 변경한다1 2
# 예: 힙 메모리를 2GB로 설정 export KAFKA_HEAP_OPTS="-Xmx2G -Xms2G"
외부 접속 설정: 외부에서 Kafka 서버에 접속하려면
server.properties파일을 수정1 2 3 4 5 6 7
# 설정 파일 열기 vi /opt/kafka/config/server.properties # 아래 내용을 찾아 주석을 해제하고 서버의 IP 주소로 변경 # advertised.listeners=PLAINTEXT://your.host.name:9092 # -> advertised.listeners=PLAINTEXT://<서버의 공인 또는 사설 IP>:9092
Zookeeper 실행 Kafka는 클러스터의 메타데이터 관리를 위해 Zookeeper를 사용 (최신 버전에서는 Zookeeper 없이 KRaft 모드로 실행 가능하지만, 여기서는 Zookeeper 기반으로 설명)
1 2 3 4 5 6
# Zookeeper를 데몬(백그라운드)으로 실행 zookeeper-server-start.sh -daemon /opt/kafka/config/zookeeper.properties # Zookeeper 프로세스가 실행 중인지 확인 jps -vm # 출력 결과에 QuorumPeerMain 이 보이면 정상
Kafka 브로커 실행
1 2 3 4 5 6
# Kafka 서버를 데몬(백그라운드)으로 실행 kafka-server-start.sh -daemon /opt/kafka/config/server.properties # Kafka 프로세스가 실행 중인지 확인 jps -vm # 출력 결과에 Kafka 가 보이면 정상
로그 확인
Kafka 서버 실행 중 발생하는 로그는
logs디렉토리에서 확인할 수 있다1 2
# 실시간으로 로그 확인 tail -f /opt/kafka/logs/server.log
This post is licensed under CC BY 4.0 by the author.