sangw0804 / study-docker

0 stars 1 forks source link

2.4 Dockerfile #2

Open sangw0804 opened 3 years ago

sangw0804 commented 3 years ago

1. 이미지를 생성하는 방법

도커파일을 사용하는 이유? => 이미지 생성 과정을 시스템화 할 수 있고, 자유롭게 커스텀 할 수 있음.


2. Dockerfile 살펴보기

mkdir docker file && cd docker file
echo test >> test.html
vim Dockerfile
FROM ubuntu:14.04
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 hello >> test2.html"]
EXPOSE 80
CMD apachectl -DFOREGROUND

ADD vs COPY

하지만 ADD 를 사용하는 것은 실제 이미지 빌드 시점에 어떤 파일이 추가될지 알 수 없으므로 지양하라고 한다

EXPOSE ?

EXPOSE 80 을 도커파일에 명시해주었다고 해서 이 이미지로 컨테이너를 실행했을 때 반드시 해당 포트가 docker0 에 연결되는 것이 아니다. 그보다는 이 이미지로 컨테이너를 만들때 해당 포트를 열어주어야 한다고 알려주는 것에 가깝다. 실제로는 -P 옵션을 사용해 주어야만 호스트 네트워크에 연결된다.

CMD vs ENTRYPOINT

요거 정확히 이해가 안되는데....


3. Dockerfile 빌드

빌드 컨텍스트

도커파일을 통해서 이미지 빌드를 시작하면 도커는 가장 먼저 빌드 컨텍스트를 읽는다. 빌드 컨텍스트 란, 이미지를 생성하는 데 필요한 각종 파일이 있는 디렉토리를 의미하며, Dockerfile 이 위치한 디렉터리가 빌드 컨텍스트가 된다.

ADD / COPY 등을 사용할 때 호스트 영역에서 읽어들이는 것이 사실 빌드 컨텍스트에서 읽어들이는 것.

빌드 컨텍스트는 이미지를 만들때 메모리에 모두 올라가는 듯... 따라서 / 같은 곳에서 Dockerfile을 빌드하지 않도록 주의! (.dockerignore)

빌드 과정 살펴보기

docker build -t myimage:0.0 ./

Dockerfile 의 명령어 한줄이 하나의 이미지( 레이어)이다. 즉, 명령어 한줄을 실행하고 이미지를 커밋하고, 다시 커밋된 이미지로 컨테이너를 생성해서 한줄을 실행하고 커밋하고,,, 이걸 반복하는 것이다.

이 과정에서 생성된 임시 컨테이너는 삭제된다.

FROM ubuntu:14.04
RUN apt-get update
RUN apt-get install apache2 -y
ADD test.html /var/www/html

위 도커파일에서 아래 몇줄을 지운 dockerfile로 다시 이미지를 빌드해 보면, 이전에 빌드했던 이미지 캐시를 사용하는 것을 알수 있다. 이게 가능한 이유는, 도커 이미지는 하나의 덩어리가 아니라 겹겹의 레이어로 구성되어 있기 때문이다. 가지고 있는 이미지 중 일부 레이어를 재사용할 수 있는 이미지를 빌드하려고 하면, 해당 레이어를 재사용하게 된다.

주의 : 도커가 같은 이미지 레이어라고 판단하는 기준은 docker file 에 있는 내용이기 때문에, 예를 들어 RUN git clone 같은 명령어를 실행하는 레이어의 경우 git 저장소의 실제 파일이 바뀌었어도 도커는 이전에 빌드된 레이어를 그대로 사용할 것이다(ADD 도 같으려나?). 이런 경우 --no-cache 옵션을 사용해서 무적권 새롭게 빌드하도록 해 주어야 한다.

멀티 스테이지 빌드

FROM golang
ADD main.go /root
WORKDIR /root
RUN go build -o /root/mainApp /root/main.go
CMD ["./mainApp"]

요렇게 이미지를 빌드하면 golang 베이스 이미지가 크기 때문에(go 빌드를 위한 여러 프로그램들이 있으므로) 큰 사이즈의 이미지가 나온다.

FROM golang as builder
ADD main.go /root
WORKDIR /root
RUN go build -o /root/mainApp /root/main.go

FROM alpine:latest # alpine 은 가장 기본적인 리눅스 베이스 이미지
WORKDIR /root
COPY --from=builder /root/mainApp .
CMD ["./mainApp"]

여기서 빌드된 이미지는 alpine 이미지 사이즈 만큼이므로 훨씬 작다.