[Docker] Dockerfile 작성하는 법 알고가자

imura·2023년 10월 28일
0

Docker

목록 보기
1/1
post-thumbnail

내 서버를 도커 컨테이너로 띄우기 위해서는 도커파일을 작성하는 방법을 알아야합니다.
백엔드 개발자로서는 무조건 공부해두는 것을 추천합니다.

Dockerfile 구성요소

  • 주의 : 작성한 순서대로 실행됩니다

기타 (코멘트, 공백, 줄바꿈)

코멘트: '#'를 사용해서 해당줄에 적습니다.
공백: '#'나 지시어(RUN 등) 앞에 공백은 무시되지만 인수로 전달된 경우는 공백이 유지됩니다.
줄바꿈: `(backtick) 또는 /(backslash)를 이용해서 해당 줄의 명령어를 끝냅니다.

# 주석입니다
RUN echo hello

RUN echo "hello \f
		  world"
# 결과물 > hello             world

RUN echo hello / 
# 결과물 > hello

ENV (환경변수)

  • 컨테이너가 실행될 때까지 유지됩니다.
    "docker run --env <'key'>=<'value'>"로도 지정 가능합니다.
ENV FOO=bar
RUN echo $FOO
# 변수 적용 > RUN echo bar

도커 빌드시에만 필요한 경우 단일 명령어로 설정하거나 ARG로 설정하는 것을 추천합니다.

RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y 

FROM

  • 도커 빌드 단계를 실행하기 위한 환경을 세팅합니다.
    a. 여러번의 빌드단계를 나눠서 실행하기 위해 'AS'로 단계 이름 지정이 가능합니다(Multi-stage build).
    b. 다중 플랫폼 이미지 사용시 플랫폼 지정이 가능합니다(--platform). 미지정시 실행하는 환경의 플랫폼을 사용합니다(mac m1의경우 amd64 등).
FROM --platform=linux/amd64 node:18-alpine as first 
COPY /app /app
...

FROM node:18-alpine
# first단계에서 빌드하거나 가져온 폴더 등을 '--from'을 통해 사용할 수 있다
COPY --from=first /app /app 

RUN

  1. shell 형식 : RUN <'command'>
    • 쉘 내에서 실행되는 방식으로 리눅스에서는 '/bin/sh -c' 와 같습니다.
  2. exec 형식 : RUN ["명령", "인수", "인수"]
    • 각각 문자열로 작성하고 쉘을 거치지 않고 실행됩니다.
    • 해당 형식으로는 "$FOO"처럼 변수는 사용할 수 없습니다. 쉘 형식 사용하거나 쉘을 직접 실행해야 가능합니다.
RUN 명령어에서 실행하는 결과는 캐싱되어 다음 단계에서 사용할 수 있습니다.
캐싱 무효화는 "--no-cache" 플래그로 가능합니다("docker build --no-cache").

CMD

  1. exec 형식(추천) : CMD ["명령", "인수", "인수"]
  2. ENTRYPOINT 기본인자: CMD ["인수1", "인수2"]
  3. shell 형식 : CMD command param1 param2

목적

이미지를 실행할 때 실행될 명령어를 설정합니다. 
CMD로 제공된 기본값이 없는 경우에는 'ENTRYPOINT"로 제공해야 합니다.

주의

CMD 명령어는 도커파일에 딱 한번만 사용합니다. 둘 이상을 나열하는 경우 마지막 CMD만 적용 됩니다.
CMD와 ENTRYPOINT 모두 JSON 배열 형식으로 작성되어야 합니다.

ENTRYPOINT

  1. exec 형식(추천) : CMD ["명령", "인수", "인수"]
  2. shell 형식 : CMD command param1 param2

CMD & ENTRYPOINT 조합시 실행 명령어 확인


1. ENTRYPOINT & CMD 둘다 없는 경우 : 에러
2. ENTRYPOINT shell형식 & CMD 모든경우 : ENTRYPOINT의 명령어 적용
3. ENTRYPOINT exec형식 & CMD 명령어 : ENTRYPOINT 명령어 + CMD 명령어

k8s definetion 파일에서 CMD, ENTRYPOINT 설정하는 방법

  • command와 ENTRYPOINT가 동일한 설정값
  • args와 CMD가 동일한 설정값
apiVersion: v1
kind: Pod
metadata:
 name: test
spec:
 containers:
 - name: test
   image: test-img
   command: ["node"] // = ENTRYPOINT 동일
   args: ["main"] // = CMD 동일

COPY

  • 파일을 복사해서 경로에 옮길 수 있습니다.
# hom으로 시작하는 파일
COPY hom* /mydir/

# home.txt 처럼 특정 위치 와일드카드 처리
COPY hom?.txt /mydir/

ADD

  • 파일을 복사해서 경로에 옮길 수 있습니다.
    COPY와 비슷하지만 추가적으로 원격파일 체크섬 확인과 git 레파지토리 추가가 가능합니다.

EXPOSE

  • 서버가 수신하고 있는 네트워크 포트를 설정합니다. 프로토콜 미지정시 기본값은 TCP입니다.
EXPOSE 3000

EXPOSE와 관계없이 "docker run -p <'host-port'>:<'container-port'>"방식으로 리디렉션이 가능합니다.

ARG

  • 'docker build'시 변수 전달이 가능합니다.
    ("--build-arg <'varname'>=<'value'>")
# docker build -t test-image --build-arg NODE_ENV=test
# NODE_ENV에는 test가 들어갑니다
# 기본값 설정가능
ARG NODE_ENV = development

그외

WORKDIR

  • 모든 과정에서 실행할 작업디렉토리 설정

USER

  • 사용할 사용자나 그룹을 지정

SHELL

  • 기본쉘 재정의 가능

번외) .dockerignore

.gitignore 파일처럼 도커 이미지 빌드에 필요하지 않은 목록들을 제외시킬 수 있습니다. 도커 이미지의 크기 감소에도 도움이 됩니다.
예시처럼 Dockerfile과 같은 패턴으로 파일명을 작성해야 합니다.

예시

  • dockerignore에 적어둔 파일을 빌드시 사용하려고 하면 에러가 발생합니다.
    (failed to compute cache key: "/package.json" not found: not found)
# Dockerfile

FROM node:18-alpine

ENV FOO=bar
RUN echo $FOO

COPY package.json .

---
# Dockerfile.dockerignore

package.json

참고문서

Docker 공식사이트

0개의 댓글