ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Dockerfile 작성방법, 운영에서 알아야 할 주의 사항!
    [IT] 공부하는 개발자/Open Source 2023. 4. 21. 10:56

     

    Docker image 이란?

    도커 이미지는 도커 컨테이너를 실행하기 위한 파일 시스템과 실행할 애플리케이션에 대한 설정 정보를 포함하는 템플릿입니다.

    도커 이미지는 다른 이미지와 레이어를 공유하여 생성됩니다. 새로운 이미지를 생성할 때, 이전 이미지의 레이어를 사용하여 이미지를 빌드합니다. 이전 이미지와 동일한 레이어가 있는 경우, 해당 레이어는 새로 생성하지 않고 재사용됩니다. 이렇게 함으로써, 도커 이미지를 더욱 효율적으로 빌드하고 저장할 수 있습니다.

    도커 이미지는 Docker Hub와 같은 이미지 레지스트리에 저장됩니다. 이미지 레지스트리는 도커 이미지를 중앙에서 저장하고 배포하기 위한 서버입니다. 사용자는 이미지 레지스트리에서 이미지를 다운로드하여 도커 컨테이너를 실행할 수 있습니다.

    도커 이미지는 불변성 유지하므로, 이미지를 수정하려면 새로운 이미지를 빌드해야 합니다. 이렇게 함으로써, 이미지에 대한 변경 사항을 추적 있으며, 이미지를 다른 환경에서 재사용할 있습니다. 또한, 이미지를 공유하여 다른 사용자와 협업하고, 더욱 효율적으로 애플리케이션을 배포할 있습니다.


     

     

     

    Dockerfile 이란?

    Dockerfile은 Docker 이미지를 빌드하기 위해 필요한 모든 정보와 명령어를 포함하는 스크립트 파일입니다.

    Dockerfile을 사용하여 Docker 이미지를 정의하면 Docker 이미지를 빌드하고 배포하는 프로세스를 자동화할 수 있습니다.

    예를 들어, Dockerfile에서는 베이스 이미지, 패키지 설치, 애플리케이션 파일 복사, 포트 노출, 컨테이너 실행 등의 작업을 수행할 수 있습니다.

    Dockerfile 사용하면 동일한 환경에서 Docker 이미지를 반복적으로 빌드하고 배포 있으며, 이미지를 빌드하는 과정에서 일어나는 모든 변경사항을 추적할 있습니다. 이렇게 함으로써, 개발자는 애플리케이션의 빠른 개발 배포를 돕는 동시에, 개발/운영 환경의 일관성을 유지할 있습니다.

     


     

    예시: node.js 애플리케이션을 빌드하는 Dockerfile 작성

    FROM node:14-alpine
    WORKDIR /app
    COPY . .
    RUN npm install
    CMD ["npm", "start"]

     

    1. FROM 명령어로 베이스 이미지를 정의. 도커 레지스트리에서 가져올 베이스 이미지
    2. WORKDIR 명령어로 애플리케이션을 실행할 작업 디렉토리를 설정. 도커 컨테이너의 루트 디렉토리가 /app 이 됨
    3. COPY 명령어로 로컬 디렉토리의 파일을 Docker 이미지의 작업 디렉토리로 복사함
    4. RUN 명령어는 Docker 이미지 빌드 중에 실행 명령어를 정의. 예제에서는 npm install 실행하여 애플리케이션에 필요한 노드 패키지를 설치함
    5. CMD 명령어는 컨테이너가 시작될 실행 기본 명령어를 정의. 예제에서는 npm start 실행하여 애플리케이션을 시작.

     

    제가 처음에 도커 파일을 작성할 때는 실행 시점을 잘 이해하지 못해서 오류를 많이 발생시켰어요. 4의 RUN으로 정의한 커맨드는 빌드 단계에서 실행되고, 5의 CMD로 정의한 커맨드는 내가 컨테이너를 실제로 시작시킬 때에 (docker run $컨테이너이름) 실행된다는 것을 주의해야 합니다 !!


     

    Dockerfile에 사용되는 유용한 명령어

    Dockerfile은 Docker 이미지를 빌드하기 위한 스크립트 파일입니다. 여기에는 다양한 명령어가 있으며, 이 중에서 몇 가지 유용한 명령어는 다음과 같습니다.

    1. FROM 이미지의 베이스 이미지를 설정하는 명령어입니다. 새로운 이미지를 만들 때 이전 이미지를 기반으로 하기 때문에 이 명령어는 Dockerfile에서 가장 중요한 명령어 중 하나입니다.
    2. RUN 새로운 레이어에서 명령어를 실행합니다. 이 명령어는 Docker 이미지를 빌드할 때 필요한 패키지, 라이브러리, 소프트웨어 등을 설치할 때 유용합니다.
    3. COPY 호스트 머신의 파일을 Docker 이미지로 복사합니다. 이 명령어를 사용하면 Docker 이미지 내부에 파일을 추가하거나 변경할 수 있습니다.
    4. ADD COPY 명령과 유사하지만 좀 더 많은 기능을 제공합니다. URL에서 파일을 다운로드하거나 압축 파일을 푸는 등의 작업을 수행할 수 있습니다.
    5. EXPOSE 컨테이너가 사용할 포트를 설정하는 명령어입니다. 이 명령어를 사용하면 Docker 호스트에서 컨테이너에 접근할 수 있는 포트를 설정할 수 있습니다.
    6. CMD 컨테이너가 시작될 때 실행할 명령을 설정합니다. 이 명령어를 사용하면 이미지를 실행할 때 필요한 명령어를 미리 설정할 수 있습니다.
    7. ENV 환경 변수를 설정하는 명령어입니다. 이 명령어를 사용하면 컨테이너 내부에서 사용할 환경 변수를 설정할 수 있습니다. 환경변수는 이미지 빌드할 때 설정되지만 컨테이너를 실행할 때에 docker run -e 옵션을 사용해서 주입하는 것도 가능합니다.
    8. WORKDIR 작업 디렉토리를 설정하는 명령어입니다. 이 명령어를 사용하면 Docker 이미지 내부에서 작업할 디렉토리를 설정할 수 있습니다.
    9. ARG Docker 빌드 시점에서 전달할 인수를 설정하는 명령어입니다. 이 명령어를 사용하면 Docker 이미지 빌드 시 변수를 전달할 수 있습니다.
    10. ENTRYPOINT 컨테이너가 시작될 실행될 기본 실행 파일 또는 명령을 지정합니다. ENTRYPOINT 명령어는 Dockerfile에서 하나만 사용할 있습니다. ENTRYPOINT Dockerfile 있는 명령어 가장 먼저 실행되며, CMD 명령어와 함께 사용될 경우 CMD 명령어는 ENTRYPOINT 명령어에서 지정된 명령어의 인자로 전달됩니다.

     


     

    ENTRYPOINT & CMD 사용 예시

    FROM alpine:latest
    ENTRYPOINT ["sh", "-c"]
    CMD ["echo Hello World! && ls -la"]

    ENTRYPOINT 명령어에 sh -c를 사용하여 여러 커맨드를 순차적으로 실행할 수 있도록 하고, CMD 명령어에는 두 개의 커맨드를 && 으로 연결하여 전달함. 이 이미지를 사용하여 컨테이너를 실행하면 실행시점에 echo와 ls 명령어가 차례대로 실행되게 될 것이다.

     


     

     

    주의 사항

     

    1. 명령어 순서: Dockerfile에서는 명령어의 순서가 매우 중요합니다. Docker 이전 레이어에서 생성된 캐시를 재사용하여 이미지를 빌드합니다. 따라서, 자주 변경되는 명령어는 뒤쪽에 배치하여 캐시의 재사용을 최대화하고, 적게 변경되는 명령어는 앞쪽에 배치하여 이미지를 가능한 빠르게 빌드할 있도록 해야 합니다.
    2. 불필요한 파일 포함: Docker 이미지는 가능한 작아야 하므로, 불필요한 파일이나 라이브러리를 포함하지 않도록 주의해야 합니다. COPY 명령어를 사용하여 애플리케이션 파일만 복사하고, 필요한 라이브러리만 설치해야 합니다.
    3. 보안: Docker 이미지는 보안 취약점을 가질 있으므로, 가능한 최소한의 권한으로 실행되도록 작성해야 합니다. 불필요한 root 권한을 피하고, 적절한 사용자 및 그룹을 사용하여 보안을 강화해야 합니다.
    4. 의존성 버전: Dockerfile에서 사용되는 의존성의 버전은 가능한 명시적으로 지정해야 합니다. 이를 통해 다른 개발자나 운영자가 이미지를 재현하거나 버전 충돌을 피할 있습니다.
    5. Kubernetes와 동시 사용 시에, 우선 적용되는 커맨드에 대해 인지해야 합니다.
      1. 쿠버네티스에서 직접 지정한 커맨드: 쿠버네티스의 command와 args 필드에 직접 커맨드와 인자를 지정한 경우, 이 값들이 Dockerfile에 작성된 CMD와 ENTRYPOINT 명령어를 덮어씁니다.
      2. Dockerfile의 CMD와 ENTRYPOINT 명령어: Dockerfile에서 CMD와 ENTRYPOINT 명령어를 작성한 경우, 해당 명령어가 적용됩니다.

     


     

    보안 강화 예시

    FROM ubuntu:latest
    
    # 애플리케이션 사용자 생성
    RUN groupadd -r myapp && useradd --no-log-init -r -g myapp myapp
    
    # 애플리케이션 코드 복사
    COPY app /app
    
    # 애플리케이션 실행
    USER myapp
    CMD ["/app"]

    myapp이라는 애플리케이션 사용자를 생성하고 이 사용자를 사용하여 애플리케이션을 실행함으로써, 애플리케이션을 root 권한이 아닌 그룹 권한으로 실행하여 보안성을 향상할 수 있습니다.

     


     

    k8s와 동시 사용 시 커맨드 override 예시

     

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    spec:
      containers:
      - name: my-container
        image: my-image
        command: ["sleep"]
        args: ["3600"]

     

    위와 같은 kuberntes 파드 정의를 가지고 도커 컨테이너를 생성한다면, Dockerfile에 작성된 CMD는 무시되고, sleep 3600 이 실행되게 됩니다.


     

     

    댓글

Copyright in 2020 (And Beyond)