효율적으로 작성하는 Docker 컨테이너의 기본 Dockerfile
이 내용은 아직 번역본이 없습니다.
실제 작동하는 이미지를 기반으로 설명을 풀어가겠습니다. 가벼운 마음으로 읽어보세요 :) 정답은 온몸 비틀기
도커와 컨테이너 기술
- 앞서 살펴본 바와 같이 도커(Docker)는 컨테이너 기술을 사용하여 애플리케이션을 패키징하고 배포하는 데 사용되는 플랫폼입니다.
- 도커의 핵심 개념 중 하나는
Dockerfile
입니다.Dockerfile
은 도커 이미지를 빌드하기 위한 텍스트 파일로, 애플리케이션의 환경을 정의하고 구성하는데 사용됩니다. - 이 파일은 애플리케이션을 실행하는 데 필요한 모든 설정, 종속성 및 명령을 정의합니다.
- 또한
Dockerfile
은 셸스크립트랑 별반 다를 것이 없습니다. 따라서 리눅스에 대한 기본적인 지식이 필요합니다. 권한, 사용자, 좀비 프로세스 처리 등등. - 서버를 설정하는 방법 그대로 그 순서로
Dockerfile
을 만들고 이미지를 만들고 활용 하는 것 이라고 간단히 이해하시면 편하실 겁니다.
Dockerfile의 구조
1. 베이스 이미지 선택
- 먼저 어떤 기반 이미지를 사용할지를 지정합니다. 베이스 이미지는 미리 구성된 운영 체제 및 소프트웨어 패키지를 포함하고 있습니다. 보통은 공식적으로 제공되는 베이스 이미지를 사용하거나 직접 만들어 사용할 수 있습니다.
2. 환경 설정
- 애플리케이션을 실행하는 데 필요한 환경을 설정합니다. 이는 환경 변수 설정, 작업 디렉토리 변경, 사용자 및 그룹 설정 등을 포함할 수 있습니다.
3. 애플리케이션 종속성 설치
- 애플리케이션이 필요로 하는 종속성을 설치합니다. 이는 패키지 관리자를 통해 소프트웨어를 설치하거나 소스 코드를 다운로드하고 컴파일하는 등의 작업을 포함할 수 있습니다.
4. 애플리케이션 파일 추가
- 애플리케이션의 소스 코드나 실행 파일 등을 이미지에 추가합니다. 이를 통해 이미지에 애플리케이션을 포함할 수 있습니다.
5. 포트 노출 및 명령 정의
- 애플리케이션이 사용하는 포트를 노출하고, 실행될 명령을 정의합니다. 이는 컨테이너가 실행될 때 자동으로 실행될 명령을 지정하는 CMD 또는 ENTRYPOINT 지시문을 사용하여 수행됩니다.
6. 빌드 및 이미지 생성
- 사용해서 도커 이미지를 빌드합니다. 이는 docker build 명령어를 사용하여 수행됩니다. Dockerfile에 정의된 각 단계는 캐시되어 이전에 빌드 한 이미지에서 재사용될 수 있으므로, 이미지 빌드 시간을 최소화할 수 있습니다.
직접 뜯어봅시다
제가 만든 이미지 중에서 아키텍쳐 그리고 멀티스테이지 빌드 까지 사용하는 이미지여서 가져와 봤습니다. 앞으로 천천히 알아보겠습니다. 모든 글을 읽고 나면, 아키텍쳐별로, 멀티스테이지 빌드 등 모든 개념을 이해하고 활용하실 수 있습니다.
NavyStack 깃허브 answer-docker
총 3개의 스테이지로 이루어져 있습니다. 사용되는 언어는 Golang, Node.js(JavaScript)입니다. 또한 아키텍쳐별로, 미세하게 조정이 필요했습니다. 최종 이미지에서는 레이어 수를 줄이기 위해 명령어를 하나로 줄을 세우는 모습까지 보여줍니다.
#FROM node:lts-bookworm AS git
#ARG TARGETARCHARG PLUGIN_LIST_FILE=/incubator-answer/script/plugin_list
WORKDIR /incubator-answer/RUN git clone --recurse-submodules -j8 --depth 1 \ https://github.com/apache/incubator-answer.git /incubator-answer/
#RUN case "$TARGETARCH" in \ "arm") \ PLUGIN_LIST="github.com/apache/incubator-answer-plugins/connector-basic@latest \ github.com/apache/incubator-answer-plugins/connector-github@latest \ github.com/apache/incubator-answer-plugins/connector-google \ github.com/apache/incubator-answer-plugins/storage-s3@latest \ github.com/apache/incubator-answer-plugins/editor-formula@latest \ github.com/apache/incubator-answer-plugins/cache-redis@latest";; \ "amd64"|"arm64") \ PLUGIN_LIST="github.com/apache/incubator-answer-plugins/connector-basic@latest \ github.com/apache/incubator-answer-plugins/connector-github@latest \ github.com/apache/incubator-answer-plugins/connector-google \ github.com/apache/incubator-answer-plugins/storage-s3@latest \ github.com/apache/incubator-answer-plugins/editor-chart@latest \ github.com/apache/incubator-answer-plugins/editor-formula@latest \ github.com/apache/incubator-answer-plugins/cache-redis@latest";; \ *) \ echo "Unsupported architecture: $TARGETARCH" && \ exit 1;; \ esac && \ if [ ! -f "$PLUGIN_LIST_FILE" ]; then \ echo "Plugin list file '$PLUGIN_LIST_FILE' not found. Exiting."; \ exit 1; \ fi && \ { \ cat "$PLUGIN_LIST_FILE"; \ echo "$PLUGIN_LIST"; \ } | sort | uniq > "$PLUGIN_LIST_FILE"
#FROM node:lts-bookworm AS golang-builder
#ARG TARGETARCHARG GOLANG_VERSION=1.22.0ARG CGO_EXTRA_CFLAGS
#ENV PNPM_HOME="/pnpm"ENV GOPATH="/go"ENV GOROOT="/usr/local/go"ENV PACKAGE="github.com/apache/incubator-answer"ENV PATH="$PNPM_HOME:$GOPATH/bin:$GOROOT/bin:$PATH"ENV BUILD_DIR ${GOPATH}/src/${PACKAGE}ENV ANSWER_MODULE ${BUILD_DIR}
COPY --from=git /incubator-answer/ ${BUILD_DIR}
WORKDIR ${BUILD_DIR}#RUN case "$TARGETARCH" in \ "arm") \ GO_PKG="go${GOLANG_VERSION}.linux-${TARGETARCH}v6l.tar.gz" && \ wget https://go.dev/dl/$GO_PKG && \ tar -C /usr/local -xzf $GO_PKG && \ rm $GO_PKG && \ corepack enable && \ export NODE_OPTIONS="--max-old-space-size=8096" && \ pnpm add -D -r @swc/core-linux-arm-gnueabihf @swc/core @swc/cli @swc/wasm swc-loader;; \ "amd64"|"arm64") \ GO_PKG="go${GOLANG_VERSION}.linux-${TARGETARCH}.tar.gz" && \ wget https://go.dev/dl/$GO_PKG && \ tar -C /usr/local -xzf $GO_PKG && \ rm $GO_PKG && \ corepack enable ;; \ *) \ echo "Unsupported architecture: $TARGETARCH" && \ exit 1 ;; \ esac && \ make clean build
RUN chmod +x answerRUN ["/bin/bash","-c","script/build_plugin.sh"]RUN cp answer /usr/bin/answer
RUN mkdir -p /data/uploads \ && chmod 777 /data/uploads \ && mkdir -p /data/i18n \ && cp -r i18n/*.yaml /data/i18n#FROM debian:bookworm-slim AS finalLABEL maintainer=github.com/NavyStack/answer-docker
#ENV TIMEZONE="Asia/Seoul" \ USER="answer" \ UID="1001" \ GID="1001"
#RUN groupadd --gid $GID $USER \ && useradd --uid $UID --gid $GID --home-dir /data/ --shell /bin/bash $USER \ && mkdir -p /data/ \ && chown -R $USER:$USER /data/ \ && apt-get update \ && DEBIAN_FRONTEND=noninteractive \ apt-get -y --no-install-recommends install \ ca-certificates \ curl \ tini \ gettext \ openssh-client \ sqlite3 \ gnupg \ tzdata \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* \ && ln -sf /usr/share/zoneinfo/$TIMEZONE /etc/localtime \ && echo "$TIMEZONE" > /etc/timezone
#COPY --from=golang-builder --chown=$USER:$USER /usr/bin/answer /usr/bin/answerCOPY --from=golang-builder --chown=$USER:$USER /data /dataCOPY --from=git --chown=$USER:$USER /incubator-answer/script/entrypoint.sh /entrypoint.sh
WORKDIR /dataUSER $USER
#VOLUME /dataEXPOSE 80
#ENTRYPOINT ["tini", "--", "/entrypoint.sh"]
수고 많으셨습니다. 감사합니다.
Askfront.com (에스크프론트)
초보자도 편하게 질문할 수 있는 자유로운 포럼을 준비했어요! 💬
에스크프론트
에서는 NavyStack 가이드뿐만 아니라, 궁금한 모든 질문을 환영합니다. 😊검색해도 원하는 답을 찾지 못해 답답했던 경험 있으시죠?
🔍 그럴 땐 부담 없이 질문해 주세요!
함께 이야기하며 답을 찾아갈 수 있을 거예요. 🤝
제가 직접 답변드릴 수 있다면 언제든 도와드릴게요. 감사합니다! 🙏