[Docker] Dockerfile (1)

Parker cho·2022년 6월 21일
0

도커

목록 보기
4/4
post-thumbnail

이미지를 생성하는 방법

도커 파일을 사용하지 않을 경우

  1. 기본 이미지(우분투, CentOS 등) 기반 컨테이너 생성
  2. 환경 설치 후 컨테이너에서 잘 동작하는 것을 확인
  3. 컨테이너를 이미지로 커밋

단점

  • 수작업으로 패키지를 설치해야함
  • 환경설정을 할 때 어떤 과정을 거쳐야 하는지 알지 못함

도커 파일을 사용 할 경우

  • 환경설정 할 때 수행해야 하는 명령어와 셸 스크립트를 하나의 파일에 기록하고 관리 할 수 있음
  • 깃과 같은 개발 도구를 통해 애플리케이션의 빌드 및 배포를 자동화 할 수 있음
  • 도커 허브에 이미지 자체를 배포하는 대신 이미지를 생성하는 방법을 기록해 놓은 Dockerfile 을 배포 할 수도 있음

Dockerfile 작성

명령어

  • FROM: 생성할 이미지의 베이스 이미지

    • 사용하려는 이미지가 로컬에 존재하지 않을 경우 자동으로 pull 함
  • MAINTAINER: 이미지를 생성한 개발자의 정보를 나타냄

    • 근데 1.13.0 버전이후로 deprecated 됨
  • LABEL: 이미지에 메타데이터를 추가 함 “키=값" 형태로 저장되며 이후 docker inspect 명령어로 이미지의 정보를 확인 할 수 있음

  • RUN 이미지를 만들기 위해 컨테이너 내부에서 명령어를 실행함

  • ADD: 로컬에 있는 파일을 이미지에 추가함

  • WORKDIR: 명령어를 실행할 디렉터리를 나타냄

    • CD 랑 같다고 생각하면 이해하기 쉬움
  • EXPOSE: 이미지에서 노출할 포트를 설정함

    • 반드시 호스트의 포트와 바인딩 되는 것은 아님
    • run 명령어에서 -P플래그를 사용해 컨테이너의 포트를 호스트에 퍼블리시 할 수 있음
  • CMD: 컨테이너가 시작 할 때 실행할 명령어를 설정함

    • Docker 파일에서 단 한번만 사용 할 수 있음
    • 하나의 터미널을 차지하는 프로세스가 실행되었을 때 호스트는 -d 옵션을 사용해야함

작성 예시

FROM ubuntu:14.04
LABEL maintainer "asdf"
LABEL purpose="practice"

RUN apt-get update
RUN apt-get install apache2 -y
ADD egg.html /var/www/html

WORKDIR /var/www/html
RUN ["/bin/bash", "-c", "echo hello > test2.html"]

EXPOSE 80
CMD apachectl -DFOREGROUND

이미지 생성

docker build -t egg:0.0 ./
  • -t: 생성될 이미지의 이름을 설정함
    • 사용하지 않으면 16진수의 형태로 이미지가 저장되므로 가급적이면 사용하는 것이 좋음
  • 명령어의 끝에는 Dockerfile 이 저장된 경로를 입력함

컨테이너 실행

docker run -d -P --name eggserver egg:0.0
  • -P EXPOSE의 모든 포트를 호스트에 연결하도록 설정
  • docker port 명령어로 어디랑 포트포워딩 됐는지 확인가능
docker images --filter "label=purpose=practice"
  • 위와 같이 라벨을 통해 이미지목록 필터링 가능

빌드 과정

빌드 컨텍스트

  • 이미지를 생성하는 데 필요한 모든 것을 담고 있는 디렉터리를 의미함
    • Dockerfile이 위치한 디렉터리임
  • 컨텍스트는 build 명령어의 맨 마지막에 지정된 위치에 있는 파일을 전부 포함함
    • 따라서 Dockerfile이 위치한 곳에는 이미지 빌드에 필요한 파일만 있는 것이 바람직함
  • 불필요한 파일이 포함되면 빌드 속도가 느려지고 호스트가 메모리를 지나치게 점유 할 수 있음
    • 이를 방지하기 위해 .gitignore 와 유사한 .dockerignore 파일을 작성할 수 있음
      • 해당 파일에 명시된 이름의 파일을 컨텍스트에서 제외함

dockerignore 예시

# nano .dockerignore
test2.html
*.html
*/*.html
test.htm? ex) test.htmb, test.html, .... etc

컨테이너 생성과 커밋

  • 이미지로 만드는 과정이 하나의 컨테이너에서 일어나는 것이 아님
  • ADD, RUN 등의 명령어가 실행될 때 마다 새로운 컨테이너가 하나씩 생성되며 이를 이미지로 커밋함
    • 이전 Step 이미지 기반으로 생성
    • 이미지의 빌드가 완료되면 Dockerfile 의 명령어 줄 수 만큼의 레이어가 존재하게 됨

캐시를 이용한 이미지 빌드

  • 이전에 빌드할 때 사용한 이미지 레이어는 캐시로 저장한 다음
    • 다음에 동일한 이미지 레이어를 사용하는 빌드가 있을 경우 캐시를 활용함

예시

# nano Dockerfile2
FROM ubuntu:14.04
LABEL maintainer "chobe1 <chobe1@naver.com>"
RUN apt-get update

캐시를 사용하고 싶지 않은 경우

  • git clone 등의 명령어를 사용해 빌드 할 경우
    • 이전의 이미지 레이어만 가져오기때문에 새로운 코드를 반영할 수 없음
  • build 명령어에 —no-cache 옵션을 추가해서 해결 할 수 있음
docker build --no-cache -t egg:0.0 ./
  • 또는 Dockerfile에 일부 내용을 추가해서 사용
docker build --cache-from nginx -t egg:0.0

멀티 스테이지를 이용한 Dockerfile 빌드

  • 일반적으로 애플리케이션을 빌드 할 경우 다량의 의존성 패키지와 라이브러리가 필요함
  • Dockerfile 을 통해 빌드 할 때 단순한 기능을 제공하는 애플리케이션도 용량이 커질 수 있음
  • 이런 문제점을 여러개의 이미지를 사용해서 해결 할 수 있음

작성예시

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

FROM alpine:latest
WORKDIR /root

# /root/mainApp 을 alpine:latest 이미지에 복사 from=0 첫번째 FROM 에서 빌드된 이미지의 최종상태
COPY --from=0 /root/mainApp .
CMD ["./mainApp"]
# 특정 단계의 이미지에 별도의 이름을  정의해 사용하는 경우
FROM golang as builder
ADD main.go /root
WORKDIR /root
RUN go build -o /root/mainApp /root/main.go
FROM alpine:latest
WORKDIR /root
COPY --from=builder /root/mainApp .
CMD ["./mainApp"]
profile
true nobility is being superior to your former self

0개의 댓글