DockerFile이란?
DockerFile은 Docker 이미지가 어떤 단계를 거쳐 빌드되야 하는지를 담고있는 텍스트 파일이다. 파일에 나열된 명령문을 차례대로 수행하여 이미지를 생성할 수 있다.
DockerFile 명령어
DockerFile에서 사용되는 주요 명령어들을 정리해보았다.
FROM
베이스 이미지를 지정하는 명령어이다. 컨테이너를 특정한 이미지를 기반으로 추가적인 세팅을 할 수 있는데 이것이 베이스 이미지이다.
애플리케이션을 실행할 때 특정 버전의 JDK가 설치되어있는 환경을 원할 수도 있고, 특정 버전의 Node가 깔려있는 환경을 원할 수도 있을 것이다.
상황에 따라 필요한 베이스 이미지를 잘 선택하면 된다.
# FROM 이미지명(:태그명) (태그명을 생략하면 latest가 들어간다)
# 예시 1
FROM openjdk:17-jdk
# 예시 2
FROM node:20
COPY
호스트 컴퓨터에 있는 디렉터리나 파일을 이미지로 복사하기 위해서 사용되는 명령어이다. 절대 경로와 상대 경로를 모두 지원한다.
# COPY (호스트 컴퓨터에 있는 복사할 파일의 경로) (컨테이너에서 파일이 위치할 경로)
# 예시
COPY build/libs/*SNAPSHOT.jar application.jar
복사할 때 복사가 되지 않길 바라는 파일들은 .dockerignore 파일을 만들어 지정해주면 된다. .gitignore를 생각하면 쉽다.
현재 디렉토리의 모든 파일과 디렉토리를 컨테이너의 작업 디렉토리로 복사하는 아래 명령어는 자주 사용하니 기억해두면 좋다.
COPY . .
ENTRYPOINT
컨테이너가 생성되고 최초로 실행할 때 수행되는 명령어를 뜻한다. 이미지를 컨테이너로 띄울 때 항상 실행되야 하는 커맨드를 지정할 때 사용한다. 추가적인 명령어 존재 여부와 상관 없이 무조건 실행된다.
# ENTRYPOINT [명령문, 파라미터1, 파라미터2, ...]
# 예시
ENTRYPOINT ["java", "-jar", "/application.jar"]
CMD
CMD 명령문은 이미지를 컨테이너로 띄울 때 디폴트로 실행할 커맨드를 지정한다. 하지만 ENTRYPOINT와는 다르게 docker run 명령 실행시 파라미터를 넘기면 덮어쓰기가 가능하다.
그래서 보통 ENTRYPOINT와 같이 사용하며 추가적인 파라미터를 지정할 때 많이 사용된다.
아래와 같이 도커파일이 작성되어 있다고 생각해보자.
ENTRYPOINT ["node"]
CMD ["index.js"]
그냥 'docker run (이미지명)'으로 컨테이너를 띄우면 그대로 'node index.js'가 수행될 것이다.
하지만 'docker run (이미지명) main.js'로 컨테이너를 띄우면 CMD에 작성한 부분이 덮어씌워져 'node main.js'가 수행된다.
RUN
이미지 생성 과정에서 명령어를 실행시켜야 할 때 사용한다.
# RUN (명령문)
RUN npm install -g pm2
위와 같이 보통 특정 소프트웨어를 설치하기 위해 많이 사용된다.
WORKDIR
WORKDIR는 컨테이너에서 작업 디렉토리로 전환하기 위해 사용되는 명령어이다. WORKDIR로 작업 디렉토리를 전환하면 그 이후 등장하는 모든 RUN, ENTRYPOINT, CMD, COPY 등 명령문은 해당 디렉터리를 기준으로 실행된다.
컨테이너 내부 폴더를 깔끔하게 관리하기 위해 사용한다.
FROM node:20
WORKDIR /app
COPY package*.json .
위와 같이 코드를 작성하면 '/app' 디렉토리에 package.json과 package-lock.json 파일이 복사될 것이다.
EXPOSE
EXPOSE는 단순히 컨테이너가 어떤 네트워크 포트를 사용하는지를 명시적으로 표시하는 명령어이다. 이 명령어를 사용한다고 해서 호스트에서 이 포트로 컨테이너에 접근할 수 없다.
다소 헷갈리는 명령어인데 공식 홈페이지에도 다음과 같이 나와있다.
'EXPOSE 명령어는 실제로 포트를 노출시키지 않는다. 이 명령어는 이미지를 빌드하는 사람과 컨테이너를 실행하는 사람 간에 어떤 포트가 노출될 에정인지에 대한 정보를 제공하는 문서화의 역할을 한다.'
EXPOSE만으로는 문서화의 역할만하고 docker run -p 명령어를 이용해 포트 매핑을 해야지만 포트가 외부에 노출되는 것이다.
# 예시
EXPOSE 8080
하지만 docker run -P 명령어를 이용해 자동 포트 매핑을 이용할 때에는 EXPOSE가 유용하다. docker run -P 명령어를 사용하면 도커가 호스트에서 사용할 임의의 포트를 자동으로 할당하고 이럴 EXPOSE에 명시된 포트에 연결해준다.
$ docker run -P (이미지명)
예를 들어, Dockerfile에서 EXPOSE 8080을 지정한 경우 위 명령을 실행하면 Docker가 호스트의 임의의 포트를 선택하여 컨테이너의 8080번 포트에 매핑하게 된다. 임의의 포트가 12345인 경우 컨테이너 외부에서 localhost:12345로 접근할 수 있게 되는 것이다.
ARG와 ENV
ARG 명령어는 docker build로 이미지를 빌드할 때, --build-arg 옵션을 이용해 넘길 수 있는 파라미터를 정의하기 위해 사용한다. ARG로 정의된 변수는 오로지 빌드 시에만 사용할 수 있다. (이미지 실행 때는 사용할 수 없다.)
(중략)
ARG NEXT_PUBLIC_BASE_URL
RUN npm install
COPY . .
RUN npm run build --next-public-base-url=$NEXT_PUBLIC_BASE_URL
(중략)
위와 같이 Dockerfile을 작성했다고 해보자. ARG로 정의된 변수는 위와 같이 빌드 시에 사용할 수 있다.
아래 같이 docker build로 이미지를 빌드할 때 --build-arg 옵션을 통해 파라미터 값을 넘길 수 있다.
$ docker build --build-arg NEXT_PUBLIC_BASE_URL=localhost:8080 .
ENV 명령어는 환경 변수를 설정하는데 사용한다. ENV로 설정된 환경 변수는 이미지 빌드 뿐만 아니라 컨테이너에서 돌아가는 애플리케이션에서도 사용되고, 접근할 수 있다.
ENV NODE_ENV development
위와 같이 Dockerfile을 작성하고 그대로 컨테이너를 실행하면 NODE_ENV에 development가 들어간 상태로 애플리케이션이 실행될 것이다.
ENV로 정의된 변수는 docker run을 할 때 -e 옵션을 통해 기본값을 위와 같이 설정해두더라도 오버라이드가 가능하다.
$ docker run -e NODE_ENV=production (이미지명)
위와 같은 명령어로 컨테이너를 실행하면 NODE_ENV에 production이 들어간 상태로 애플리케이션이 실행된다.
여기까지 공부하면서 알게 된 명령어들을 모두 정리해보았다. 이 정도만 알아도 Dockerfile 작성에 큰 어려움은 없었다.
서로 다른 여러가지 프레임워크를 사용한 프로젝트들을 Dockerfile을 이용해 이미지를 만들어 보았는데 프로젝트마다 Dockerfile 작성법이 다소 다르고 알아야할 것들이 많이 있었다. 그래도 필요한 것들을 찾아보면서 어렵지않게 Dockerfile을 잘 작성할 수 있었다.
기회가 된다면 DockerFile을 작성하면서 겪었던 문제점들을 해결했던 과정도 한 번 정리해두면 좋을 것 같다.
'Docker' 카테고리의 다른 글
Docker Compose로 여러 컨테이너 띄워보기 (0) | 2024.12.03 |
---|---|
Docker Compose 개념 및 정리 (0) | 2024.12.02 |
Docker Volume 개념 및 활용 (0) | 2024.11.28 |
Docker 기본 개념 및 CLI 명령어 (3) (0) | 2024.11.27 |
Docker 기본 개념 및 CLI 명령어 (2) (0) | 2024.11.26 |