ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 도커 이미지 빌드 Dockerfile
    BackEnd/도커 2021. 3. 28. 21:40

    도커는 레이어드 파일 시스템을 기반으로 한다.

    레이어드 파일 시스템에는 AUFS, BTRDS, Overlayfs  등이 있다.


    Docker는 하나의 이미지로 부터 하나 이상의 컨테이너를 만들 수 있다. 
    이 과정은 하나의 프로그램 이미지(파일)로 부터, 여러 개의 프로세스를 실행 할 수 있는 리눅스 프로세스 모델과 매우 비슷한 측면이있다. 도커 이미지는 프로그램 이미지에 대응되며, 컨테이너는 프로세스에 대응된다.

     

    이미지는 읽기 전용과 쓰기 가능 두 가지로 나뉜다.

     

    하나의 도커 이미지로 부터 여러 개의 컨테이너를 만들려면, 도커 이미지가 "변경"이 되면 안 될 것이다. 
    프로그램의 파일이 변경되면 안 되듯이 원칙적으로 도커 이미지의 데이터는 변경이 되면 안된다.
    실제 도커를 기반으로 SaaS 환경을 구축할 경우 아예, 이미지를 읽기 전용으로 만드는 식으로 구성을 한다. 
    예를 들어 MySQL을 SaaS 형태로 제공 한다면, Mysql 소프트웨어는 이미지로 만들고, 데이터는 별도의 볼륨에 읽고/쓰는 식으로 구성을 한다.

     

    또는 이미지는 프로세스가 실행되는 파일들의 집합(환경) 이고, 프로세스는 환경(파일)을 변경할 수 있다.

    이 환경을 저장해서 새로운 이미지를 만든다.


    DockerFile 은 도커 이미지를 만들기 위한 설정 파일이다.
    베이스이미지를 명시해주고 추가적인 파일을 받기 위한 명령어를 명시 > 파일 스냅샷 
    도커 이미지는 여러개의 레이어로 되어있다. 베이스 이미지는 OS 라고 생각하면 된다.

    베이스 이미지는 읽기 전용 (rootfs,base image) 

    mysql, 우분트 기본을 바꿀 수 없지만 추가 , 수정, 삭제를 할 수 있다.

    새로운 상태를 이미지로 저장 

     

    1. docker commit 으로 새로운 이미지 생성하기 

    docker commit -name 이미지이름:태그

    docker commit 컨테이너명 이미지명:버전

    도커 컨테이너의 수정된 내용은 컨테이너가 삭제되면 모든 내용이 삭제되는데 
    컨테이너의 내용이 이미지에 영향을 끼치지 않기 때문이다.
    수정이 있을 때마다 수정된 컨테이너로 새로운 이미지를 생성해두면
    컨테이너가 삭제되어도 이미지를 통해 컨테이너를 복구할 수 있다.

    컨테이너 내에서 git 을 설치하고 이미지에 이를 반영하기 위해 commit 명령어를 이용한다.

     

    처음 ubuntu 이미지를 git 이라는 컨테이너를 생성하고 bash 로 접속하면 당연히 git 이 설치되어 있지 않다.

    git 컨테이너 내부에서 apt-get 을 통해 git 을 설치한다.

    $ apt-get update
    # apt-get install -y git

    ubuntu 에 git 이라는 태그를 달아 git 이미지로 commit 을 진행한다.

     

    $ docker commit git ubuntu:git

     

    git 태그로 새로 생성된 이미지로 git2 라는 컨테이너를 생성해 보면 내부에 git 이 설치되어 있는 것을 확인할 수 있다.


    Dockerfile 명령어 옵션

    FROM  베이스 이미지 
    RUN 컨테이너 내에서 쉘 명령어 실행
    CMD 컨테이너 기본 실행 명령어 (EntryPoint 인자로 사용)
    컨테이너 생성 시 실행할 명령어 
    EXPOSE 오픈되는 포트 정보
    ENV 환경변수 설정
    ADD 파일 또는 디렉토리 추가. url/zip 사용 가능
    파일의 압축을 풀어서 복사한다는 점이 COPY 와 다르다.
    COPY 파일 또는 디렉토리 추가
    로컬에 있는 파일을 이미지로 복사해줌 
    ENTRYPOINT 컨테이너 기본 실행 명령어
    VOLUME 외부 마운트 포인트 생성
    USER RUN, CMD, ENTRYPOINT 를 실행하는 사용자
    WORKDIR 작업 디렉토리 설정
    해당 디렉토리로 이동해서 명령어 사용
    ARGS 빌드타임 환경변수 설정 
    LABEL key-value 데이터
    ONBUILD 다른 빌드의 베이스로 사용될 때 사용하는 명령어

    docs.docker.com/engine/reference/builder

     

    * COPY 로 컨테이너에 없는 파일들을 컨테이너 안으로 옮겨준다,.

    * COPY 가 상대경로이면 WORKDIR 에서 지정한 경로로 복사 

    WORKDIR /app
    COPY entry.sh run.sh
    => /app/run.sh 로 복사

    * COPY 절대경로는 명시한 경로로 복사 

    WORKDIR /app
    COPY entry.sh /usr/bin/run.sh
    => /usr/bin 에 run.sh 로 복사

    * WORKDIR 이 없으면 root 에다가 바로 모든 걸 copy 해 

    WORKDIR 이 있으면 거기가 접근 경로가 되면서 root 에 있는 파일과 앱 실행 관련 파일이 분리

     

    * RUN, COPY, ADD 는 이미지 레이어를 만든다. 

    FROM 으로 명시한 베이스 이미지로 만든 컨테이너를 실행하여  RUN, COPY, ADD 명령어로 실행된 작업을 commit 을 통해 새로운 이미지로 만든다.

     

    * Docker는 Dockerfile 에 있는 명령어들을 하나하나 순서대로 실행시킨다. 
    각각의 명령어들이 검사되기 때문에, Docker는 새로운 이미지를 만드는 대신 재사용할 수 있는 캐시 이미지가 존재하는지 확인할 수 있다.
    만약 모든 캐시의 사용을 원하지 않는다면, docker build 커맨드에서 --no-cache=true 옵션을 사용할 수 있다. 
    ADD, COPY 커맨드에서, 캐시 체크는 컨테이너 안에 있는 파일은 비교해보지 않는다. 예를 들어, RUN apt-get -y update 커맨드를 실행할 때, 컨테이너로 업데이트된 파일은 캐시가 존재하는지 결정할 때 고려할 대상이 아니다. 이러한 경우, 커맨드 문자열만 비교하게 된다.

    * RUN 명령어와 apt-get 을 많이 사용하는데 
    apt-get upgrade 와 apt-get install 은 같은 라인에서 사용해야한다.
    구분하면 apt-get upgrade 는 동일한 문자열로 기존 캐시에서 가져다 사용하기 때문에 구버전을 사용하기 때문이다.

    RUN apt-get update && apt-get install -y \
    package-bar \
    package-baz \
    package-foo


    한 커맨드 결과를 다른 커맨드 입력으로 사용하는 파이프 기능의 경우 

    RUN wget -O - https://..  | wc -l > /number


    Docker 는 위 커맨드를 파이프의 마지막 커맨드의 반환 코드로 커맨드의 실행 결과를 판단하는 /bin/sh -c 인터프리터로 실행시킨다. 예를 들어 위의 빌드는 wget 커맨드가 실패해도 wc -l 커맨드가 성공했다면 성공적으로 마무리되고 새로운 이미지를 만들어낸다.
    만약 파이프의 어느 단계에서든지 에러를 반환할 때 커맨드의 결과를 실패로 처리하고 싶다면, set -o pipefail && 를 앞에 추가하므로써 예상치 못한 오류가 발생해도 빌드를 성공했다고 처리하는 상황을 방지할 수 있다.

    RUN set -o pipefail && wget -O - https://some.site | wc -l > /number

    2. build 명령어 이용해 이미지 만들기

    docker build -t 이름/이미지이름:태그 buildContext

    build context 는 이미지를 생성하는 데 필요한 각종 파일, 소스코드, 메타데이터 등을  담고 있는 디렉터리를 의미한다.

    docker build 명령어는 도커 데몬에 빌드 컨텍스트를 전송한다. 빌드 컨텍스트는 빌드 명령을 실행하는 디렉토리와 그 하위 디렉토리에 포함된 전체 파일이다.

     

    build context로 Dockerfile 의 위치를 명시하면 된다.  build 명령어를 실행할 때 Dockerfile 이 존재하는 디렉토리에 있다면 현재 디렉토리를 의미하는 . 을 작성한다.

    기본적으로 Dockerfile 은 여기에 위치해 있다고 가정하지만 -f 플래그로 다른 위치를 지정해줄 수도 있다.

     

    $ docker build -t ubuntu:git-dockerfile .

    mkdir -p dockerfiles context
    mv Dockerfile dockerfiles && mv hello context
    docker build --no-cache -t helloapp:v2 -f dockerfiles/Dockerfile context

     

    *개발환경에 따른 dockerfile 분리
    Dockerfile.dev
    Dockerfile.prod 
    > 빌드할 때 참조해야하는 파일명을 지정해줘야함
    > docker build -f Dockerfile.dev ./ 


    예) 노드로 웹어플리케이션 dockerfile 작성

    FROM  ubuntu:20.04 를 설치 후 

    RUN apt-get update 실행, nodjs  npm 설치 

    COPY 현재 디렉토리에서 소스를  /usr/src/app 으로 복사 (현재 디렉토리는 dockerfile 의 위치)

    WORKDIR 나의 위치를  /usr/src/app 로 이동

    RUN npm install 실행 

    EXPOSE 3000번으로 서버 실행

    CMD node app.js 명령어 실행 

     

    * local 에 있는 노드모듈은 이미지로 올릴 필요 없기 때문에 ignore 따로 정의

     

    * Dockerfile 최적화

    수정파일이 없을 경우 caching 을 이용해서 빠르게 이미지를 가져온다.

    하지만 소스를 변경하면 #2번 copy 소스부터 캐시가 깨져 이후 느려지게 된다.

    =>

    npm install 후 소스를 COPY하도록 순서를 바꾸면 오랜 시간이 소요되는 install 까지 캐시가 그대로 적용되기 때문에 

    속도를 더 빠르게 할 수 있다.

     


     

    https://velog.io/@seheon99/최고의-Dockerfile-작성을-위한-몇-가지-습관들

    https://www.44bits.io/ko/post/building-docker-image-basic-commit-diff-and-dockerfile

    https://www.44bits.io/ko/post/how-docker-image-work

    https://www.joinc.co.kr/w/man/12/docker/storage

     

    Docker storage의 거의 모든 것

    거의 모든 것이라고 하니 좀 너무 나간 것 같은 느낌이 든다. 그냥 이것 저것 다뤄 볼려고 한다. 다룰 내용은 다음과 같다. Docker에서 제공하는 스토리지 백앤드(backend)의 종류와 특징들 스토리지

    www.joinc.co.kr

     

    반응형

    'BackEnd > 도커' 카테고리의 다른 글

    도커 네트워크 관련 링크  (0) 2022.08.06
    도커 컴포즈  (0) 2021.03.24
    도커 컨테이너 실행하기  (0) 2021.03.07
Designed by Tistory.