Dockerfile이란 무엇인가?
- Coding/Docker
- 2023. 3. 2.
Docker 이미지를 생성하는 방법
1) 아무것도 존재하지 않는 이미지(우분두, CentOS 등)로 컨테이너를 생성
2) 애플리케이션을 위한 환경을 설치하고 소스코드 등을 복사해 잘 동작하는 것을 확인
3) 컨테이너를 이미지로 커밋(commit)
이 방법은 환경 구성을 위해 일일이 수작업으로 패키지를 설치하고 깃(Git)에서 복제하거나 호스트에서 복사해야한다는 단점이 있다. 그리고 직접 확인해보고 이미지로 커밋하기 때문에 이미지의 동작을 보장할 수 있다는 장점이 있다.
DockerFile로 이미지를 생성하는 방법
Docker는 이미지를 생성하는 과정을 쉽게 수행할 수 있도록 빌드(build) 명령어를 제공한다. Dockerfile 하나의 파일에 이미지 생성을 위한 내용을 기록해두면 도커는 이 파일을 읽어 컨테이너에서 작업을 수행한 뒤 이미지를 생성한다.
빌드 명령어는 Dockerfile을 읽어 이미지를 생성한다. Dockerfile을 사용하면 직접 컨테이너를 생성하고 이미지로 커밋해야하는 번거로움을 덜 수 있고, 깃과 같은 개발 도구를 통해 애플리케이션의 빌드 및 배포를 자동화할 수 있다.
Dockerfile은 애플리케이션 개발 용도 외에도 여러 목적으로 사용될 수 있으며, DockerHub 등을 통해 배포할때 이미지 자체를 대신하여 Dockerfile을 배포할 수도 있다. 실제로 도커 허브에 올려져있는 대부분의 이미지는 Dockerfile을 함께 제공하고있다.
Dockerfile 작성
예제) 아파치 웹 서버가 설치된 이미지를 빌드하는 Dockerfile
FROM ubuntu:14.04
MAINTAINER alicek106
LABEL "purpose"="practice"
RUN apt-get update
RUN apt-get install apache2 -y
ADD test.html /var/www/html/
WORKDIR /var/www/html/
RUN [ "/bin/bash", "-c", "echo hello2 >> test2.html" ]
EXPOSE 80
CMD apachectl -DFOREGROUND
Dockerfile은 한 줄이 하나의 명령어가 되고, 명령어(Instruction)를 명시한 뒤에 옵션을 추가하는 방식이다.
명령어를 소문자로 표기해도 되지만 보통 대문자로 표기한다.
명령어 정리
명령어 | 내용 |
FROM | 생성할 이미지의 베이스가 될 이미지를 뜻한다. 반드시 한번 이상 입력해야한다. 'docker run 명령어'에서 사용되는 이미지 이름과 동일하게 입력한다. 입력된 이미지가 없을때 자동으로 pull을 수행한다. |
이미지를 생성한 개발자의 정보를 나타낸다. 도커 1.13.0 버전 이후로 사용하지 않는다. |
|
LABEL | 이미지에 메타데이터를 추가한다. (키:값) 여러개의 메타데이터가 저장될 수 있으며, 'docker inspect 명령어'로 이미지의 정보를 구해서 확인할 수 있다. |
RUN | 이미지를 만들기 위해 컨테이너 내부에서 명령어를 실행한다. 예제와 같이 'apt-get update', 'apt-get install apacke2 -y' 명령어를 실행하기 위해서 아파치 웹 서버가 설치된 이미지가 생성된다. 이미지를 빌드할때 별도의 입력을 받아야하는 RUN이 있다면 build 명령어는 이를 오류로 간주한다. (불가능) |
ADD | 파일을 이미지에 추가한다. 추가하는 파일은 Dockerfile이 위치한 디렉터리인 컨텍스트(Context)에서 가져온다. |
WORKDIR | 명령어를 실행할 디렉터리를 나타낸다. 배시 셸에서 'cd' 명령어를 입력하는 것과 같다. |
EXPOSE | Dockerfile의 빌드로 생성된 이미지에서 노출할 포트를 설정한다. 단지 컨테이너의 80번 포트를 사용할 것임을 나타낼 뿐이며, EXPOSE를 설정한 이미지로 컨테이너를 생성했다고해서 반드시 이 포트가 호스트의 포트와 바인딩되는 것은 아니다. |
CMD | CMD는 컨테이너가 시작될 때마다 실행할 명령어(커맨드)를 설정한다. Dockerfile에서 한번만 사용할 수 있다. |
위 내용을 바탕으로 예제를 다시한번 보자.
FROM ubuntu:14.04
MAINTAINER alicek106
LABEL "purpose"="practice"
RUN apt-get update
RUN apt-get install apache2 -y
ADD test.html /var/www/html/
WORKDIR /var/www/html/
RUN [ "/bin/bash", "-c", "echo hello2 >> test2.html" ]
EXPOSE 80
CMD apachectl -DFOREGROUND
1) FROM
FROM ubuntu:14.04
Dockerfile에서 사용할 베이스 이미지를 ubuntu:14.04로 설정한다.
2) MAINTAINER
MAINTAINER alicek106
alicek106으로 이름을 설정한다.
3) LABEL
LABEL "purpose"="practice"
Dockerfile에 생성될 이미지의 라벨을 purpose=practice로 설정한다.
▶ 위 라벨로 이미지를 필터링하여 검색할 수 있다.
# docker images --filter "label=purpose=practice"
4) RUN
RUN apt-get update
RUN apt-get install apache2 -y
명령어를 차례대로 실행하여 아파치 웹 서버를 설치한다.
5) ADD
ADD test.html /var/www/html/
Dockerfile이 위치한 디렉터리에서 text.html 파일을 이미지의 /var/www/html 디렉터리에 추가한다.
6) WORKDIR
WORKDIR /var/www/html/
작업 디렉터리를 /var/www/html로 바꾼다.
7) RUN
RUN [ "/bin/bash", "-c", "echo hello2 >> test2.html" ]
위 6)번에서 바뀐 디렉터리에 test2.html 파일을 생성한다.
8) EXPOSE
EXPOSE 80
컨테이너가 사용해야할 포트를 80번으로 설정한다.
9) CMD
CMD apachectl -DFOREGROUND
컨테이너의 명령어를 apachectl -DFOREGROUND로 설정하여 이미지 빌드를 끝낸다.
Dockerfile 빌드
빌드 명령어는 다음과 같다.
# docker build -t mybuild:0.0 ./
명령어 | 내용 |
-t | 생성될 이미지의 이름을 설정한다. 위 명령어를 실행하면 'mybuild:0.0'이라는 이름의 이미지가 생성된다. -t 명령어를 사용하지 않으면 16진수 형태의 이름으로 생성므로 가급적이면 -t 옵션을 사용하자. |
./ | Dockerfile이 저장된 경로를 입력한다. './'는 현재 디렉토리를 의미한다. |
최종적으로 'mybuild:0.0'이라는 이름의 이미지가 생성된다. 이 이미지에는 아파치 웹 서버가 설치돼있으며, 컨테이너가 시작될때 웹 서버를 실행하도록 CMD(커맨드)를 설정했기 때문에 별다른 설정 없이도 웹 서버가 실행된다.
생성된 이미지로 컨테이너 실행해보기
# docker run -d -P --name myserver mybuild:0.0
명령어 | 내용 |
-P | 이미지에 설정된 EXPOSE의 모든 포트를 호스트에 연결하도록 설정한다. -P 옵션은 EXPOSE로 노출된 포트를 호스트에서 사용 가능한 포트에 차례로 연결하므로 이 컨테이너가 호스트의 어떤 포트와 연결됐는지 확인할 필요가 있다. |
Dockerfile 빌드 과정
1) 이미지를 빌드를 시작하면 도커는 가장 먼저 빌드 컨텍스트를 읽어들인다.
- 빌드 컨텍스트란?
- 이미지를 생성하는데 필요한 파일, 소스코드, 메타데이터 등을 담고있는 디렉터리를 말한다.
- Dockerfile이 위치한 디렉터리가 빌드 컨텍스트가 된다.
2) 빌드 컨텍스트는 Dockerfile에서 빌드될 이미지에 파일을 추가할때 사용된다.
Sending build context to Docker daemon 3.584 kb
3) 컨텍스트는 build 명령어의 맨 마지막에 지정된 위치에 있는 파일을 전부 포함한다.
- Dockerfile이 위치한 곳에는 이미지 빌드에 필요한 파일만 있는 것이 바람직하며, 루트 디렉터리(/)와 같은 곳에서 이미지를 빌드하지 않도록 주의해야한다. 컨텍스트는 단순 파일 뿐만 아니라 하위 디렉터리도 전부 포함하게 되므로 불필요한 파일이 포함될 수 있다.
- 이를 방지하기 위해서 .gitignore와 같은 .dockerignore라는 파일을 작성하여 명시된 이름의 파일을 컨텍스트에서 제외할 수 있다.
4) Dockerfile에 기록된 명령어 별로 각 Step이 수행된다.
- ADD, RUN 등의 명령어가 실행될때마다 새로운 컨테이너가 하나씩 생성되며 이를 이미지로 커밋한다.
- 즉, Dockerfile에서 명령어 한 줄이 실행될 때마다 이전 Step에서 생성된 이미지에 의해 새로운 컨테이너가 생성되며 Dockerfile에 적힌 명령어를 수행하고 다시 새로운 이미지 레이어로 저장된다.
5) 이미지의 빌드가 완료되면 Dockerfile의 명령어 줄 수 만큼의 레이어가 존재하게되며, 중간에 컨테이너도 같은 수 만큼 생성되고 삭제된다.
'도커:쿠버네티스' 책을 읽으면서 정리가 필요하다고 생각한 내용을 남겨둔다.
'Coding > Docker' 카테고리의 다른 글
[docker] jenkins 설치하고 간단한 Item 생성해서 빌드해보자 (0) | 2023.04.02 |
---|---|
docker + postgresql 설치부터 계정 생성까지 (0) | 2023.03.08 |
[Docker] Dockerfile + docker-compose 를 사용하여 SpringBoot 프로젝트 실행시키기 (1) | 2023.02.22 |
docker 에 rabbitMQ 설치하기 (with docker-compose.yml) (0) | 2021.10.13 |
쿠버네티스 배포 전략 : 롤링 업데이트 전략 vs 재생성 전략 (0) | 2021.07.13 |