Dockerfile Best Practice
이 문서는 Dockerfile 관련하여 Best Practice에 대한 내용을 공부도 할겸 번역하였다.
원본 : https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
Dockerfile 작성 모범 사례
이 문서에서는 효율적인 이미지를 구축하기위한 권장 모범 사례와 방법을 다룹니다.
Docker는 주어진 이미지를 빌드하는 데 필요한 모든 명령이 순서대로 포함 된 텍스트 파일 인 Dockerfile
에서 지침을 읽어 이미지를 자동으로 빌드합니다. Dockerfile
은 Dockerfile 참조에서 찾을 수 있는 특정 형식 및 지침 집합을 준수합니다.
Docker 이미지는 각각 Dockerfile 명령어를 나타내는 읽기 전용 레이어로 구성됩니다. 레이어는 차례로 쌓여 있고 각 레이어는 이전 레이어의 변경 사항에 대한 부분입니다.
아래 Dockerfile
을 참고하십시오.
각 명령어는 하나의 레이어를 만듭니다.
FROM
은ubuntu : 18.04
Docker 이미지에서 레이어를 생성합니다.COPY
는 Docker 클라이언트의 현재 디렉토리에서 파일을 추가합니다.RUN
은make
로 애플리케이션을 빌드합니다.CMD
는 컨테이너 내에서 실행할 명령을 지정합니다.
이미지를 실행하고 컨테이너를 생성 할 때 기본 레이어 위에 새 쓰기 가능한 계층("컨테이너 레이어")를 추가합니다. 새 파일 쓰기, 기존 파일 수정 및 파일 삭제와 같이 실행중인 컨테이너에 대한 모든 변경 사항은 이 쓰기 가능한 컨테이너 계층에 기록됩니다.
이미지 레이어(및 Docker가 이미지를 빌드하고 저장하는 방법)에 대한 자세한 내용은 스토리지 드라이버 정보를 참조하세요.
일반 지침 및 권장 사항
임시 컨테이너 만들기
Dockerfile
에서 정의한 이미지는 가능한 한 임시적인 컨테이너를 생성해야합니다. "일시적"이란 컨테이너를 중지하고 폐기 한 다음 다시 빌드하고 절대 최소 설정 및 구성으로 교체 할 수 있음을 의미합니다.
이러한 상태 비 저장 방식으로 컨테이너를 실행하는 동기에 대해 알아 보려면 "The Twelve-factor App" 방법론의 프로세스를 참조하세요.
빌드 컨텍스트 이해
docker build
명령을 실행하면 현재 작업 디렉토리를 빌드 컨텍스트 라고 합니다. 기본적으로 Dockerfile은 이곳에 있는 것으로 간주되지만 파일 플래그 (-f
)를 사용하여 다른 위치를 지정할 수도 있습니다. Dockerfile
이 실제로 어디에 있든 관계없이 현재 디렉터리에 있는 파일 및 디렉터리의 모든 하위 콘텐츠는 빌드 컨텍스트로 Docker 데몬에 전송됩니다.
빌드 컨텍스트 예제
빌드 컨텍스트에 대한 디렉토리를 만들고 그 안에
cd
로 들어갑니다. 'hello'라는 텍스트 파일에 "hello"를 쓰고 'cat'을 실행하는 Dockerfile을 만듭니다. 빌드 컨텍스트 (.
) 내에서 이미지를 빌드합니다.
Dockerfile
과hello
를 별도의 디렉토리로 이동하고 이미지의 두 번째 버전을 빌드합니다 (마지막 빌드의 캐시에 의존하지 않음).-f
를 사용하여 Dockerfile을 가리키고 빌드 컨텍스트의 디렉터리를 지정합니다.
이미지를 빌드하는 데 필요하지 않은 파일을 실수로 포함하면 빌드 컨텍스트와 이미지 크기가 커집니다. 이렇게하면 이미지를 빌드하는 시간, 이미지를 가져오고 푸시하는 시간, 컨테이너 런타임 크기가 늘어날 수 있습니다. 빌드 컨텍스트의 크기를 확인하려면 Dockerfile
을 빌드 할 때 다음과 같은 메시지를 찾으십시오.
stdin
을 통해 Dockerfile 파이프
stdin
을 통해 Dockerfile 파이프Docker는 로컬 또는 원격 빌드 컨텍스트를 사용하여stdin
을 통해Dockerfile
을 파이핑하여 이미지를 빌드 할 수 있습니다. stdin
을 통해 Dockerfile
을 파이핑하는 것은 Dockerfile을 디스크에 쓰지 않고 일회성 빌드를 수행하는 데 유용 할 수 있습니다. 또는 Dockerfile
이 생성되더라도 이후에 지속되지 않아야합니다.
이 섹션의 예제에서는 편의상 이 문서를 사용하지만
stdin
에Dockerfile
을 제공하는 모든 방법을 사용할 수 있습니다. .예를 들어 다음 명령은 동일합니다.
예제를 선호하는 접근 방식 또는 사용 사례에 가장 적합한 접근 방식으로 대체 할 수 있습니다.
빌드 컨텍스트를 보내지 않고 STDIN에서 DOCKERFILE을 사용하여 이미지 빌드
빌드 컨텍스트로 추가 파일을 보내지 않고 stdin
의 Dockerfile
을 사용하여 이미지를 빌드하려면 이 구문을 사용하십시오. 하이픈(-
)은 PATH
의 위치를 취하고 Docker가 디렉토리 대신 stdin
에서 빌드 컨텍스트 (Dockerfile
만 포함)를 읽도록 지시합니다.
다음 예제는 stdin
을 통해 전달되는 Dockerfile
을 사용하여 이미지를 빌드합니다. 데몬에 빌드 컨텍스트로 파일이 전송되지 않습니다.
빌드 컨텍스트를 생략하면 Dockerfile
이 파일을 이미지에 복사 할 필요가없는 상황에서 유용 할 수 있으며 데몬에 파일이 전송되지 않으므로 빌드 속도가 향상됩니다.
빌드 컨텍스트에서 some파일을 제외하여 빌드 속도를 높이려면 exclude with .dockerignore를 참조하세요.
Note: 이 구문을 사용하면
COPY
또는ADD
를 사용하는 Dockerfile 빌드 시도가 실패합니다. 다음 예는 이를 설명합니다.
stdin의 Dockerfile을 사용하여 로컬 빌드 컨텍스트에서 빌드
이 구문을 사용하여 로컬 파일 시스템의 파일을 사용하지만 stdin
의 Dockerfile
을 사용하여 이미지를 빌드합니다. 구문은 -f
(또는 --file
) 옵션을 사용하여 사용할 Dockerfile
을 지정하고, 하이픈(-
)을 파일 이름으로 사용하여 Docker가 stdin
에서 Dockerfile
을 읽도록 지시합니다.
아래 예제는 현재 디렉토리 (.
)를 빌드 컨텍스트로 사용하고 이 문서를 사용하여 stdin
을 통해 전달되는 Dockerfile
을 사용하여 이미지를 빌드합니다.
stdin의 Dockerfile을 사용하여 원격 빌드 컨텍스트에서 빌드
이 구문을 사용하여 stdin
의 Dockerfile
을 사용하여 원격 git
저장소의 파일을 사용하여 이미지를 빌드합니다. 구문은 -f
(또는 --file
) 옵션을 사용하여 사용할 Dockerfile
을 지정하고, 하이픈(-
)을 파일 이름으로 사용하여 Docker가 stdin
에서 Dockerfile
을 읽도록 지시합니다.
이 구문은 Dockerfile
이 포함되지 않은 저장소에서 이미지를 빌드하려는 경우 또는 저장소의 자체 포크를 유지하지 않고 사용자 정의 Dockerfile
로 빌드하려는 경우에 유용 할 수 있습니다.
아래 예제는 stdin
의 Dockerfile
을 사용하여 이미지를 빌드하고 GitHub의 "hello-world" Git 저장소에서 hello.c
파일을 추가합니다.
상세 내용
원격 Git 리포지토리를 빌드 컨텍스트로 사용하여 이미지를 빌드 할 때 Docker는 로컬 머신에서 리포지토리의
git clone
을 수행하고 해당 파일을 빌드 컨텍스트로 데몬에 보냅니다. 이 기능을 사용하려면docker build
명령을 실행하는 호스트에git
이 설치되어 있어야합니다.
.dockerignore로 제외
소스 저장소를 재구성하지 않고 빌드와 관련이없는 파일을 제외하려면 .dockerignore
파일을 사용하십시오. 이 파일은 .gitignore
파일과 유사한 제외 패턴을 지원합니다. 생성에 대한 정보는 .dockerignore 파일을 참조하십시오.
다단계 빌드 사용
다단계 빌드를 사용하면 중간 레이어 및 파일 수를 줄이기 위해 고민하지 않고 최종 이미지의 크기를 대폭 줄일 수 있습니다.
이미지는 빌드 프로세스의 마지막 단계에서 빌드되므로 빌드 캐시 활용을 통해 이미지 레이어를 최소화 할 수 있습니다.
예를 들어 빌드에 여러 레이어가 포함 된 경우 변경 빈도가 낮은 것 (빌드 캐시 재사용 가능)에서 더 자주 변경되는 순서로 순서를 지정할 수 있습니다.
애플리케이션 구축에 필요한 도구 설치
라이브러리 종속성 설치 또는 업데이트
응용 프로그램 생성
Go 애플리케이션 용 Dockerfile은 다음과 같습니다.
불필요한 패키지를 설치하지 마십시오
복잡성, 종속성, 파일 크기 및 빌드 시간을 줄이려면 "있으면 좋을 것" 이라는 이유로 추가 또는 불필요한 패키지를 설치하지 마십시오. 예를 들어 데이터베이스 이미지에 텍스트 편집기를 포함 할 필요가 없습니다.
애플리케이션 분리
각 컨테이너에는 하나의 관심사가 있어야합니다. 애플리케이션을 여러 컨테이너로 분리하면 더 쉽게 수평으로 확장하고 컨테이너를 재사용 할 수 있습니다. 예를 들어, 웹 애플리케이션 스택은 분리 된 방식으로 웹 애플리케이션, 데이터베이스 및 인 메모리 캐시를 관리하기 위해 각각 고유한 이미지가있는 3개의 개별 컨테이너로 구성 될 수 있습니다.
각 컨테이너를 하나의 프로세스로 제한하는 것은 좋은 경험 규칙이지만 강력하고 빠른 규칙은 아닙니다. 예를 들어, 컨테이너는 초기화 프로세스로 생성을 할 수 있을 뿐만 아니라 일부 프로그램은 자체적으로 추가 프로세스를 생성 할 수 있습니다. 예를 들어 Celery는 여러 작업자 프로세스를 생성 할 수 있고 Apache는 요청 당 하나의 프로세스를 생성 할 수 있습니다.
컨테이너를 가능한 한 깨끗하고 모듈식으로 유지하기 위해 최선의 판단을 사용하십시오. 컨테이너가 서로 의존성이 있는 경우 Docker 컨테이너 네트워크를 사용하여 이러한 컨테이너가 통신 할 수 있는지 확인할 수 있습니다.
레이어 수 최소화
이전 버전의 Docker에서는 성능을 보장하기 위해 이미지의 레이어 수를 최소화하는 것이 중요했습니다. 이 제한을 줄이기 위해 다음 기능이 추가되었습니다.
RUN
,COPY
,ADD
명령어 만 레이어를 생성합니다. 다른 지침은 임시 중간 이미지를 만들고 빌드 크기를 늘리지 않습니다.가능하면 [다단계 빌드] (multistage-build.md)를 사용하고 필요한 아티팩트 만 최종 이미지에 복사합니다. 이를 통해 최종 이미지의 크기를 늘리지 않고도 중간 빌드 단계에 도구 및 디버그 정보를 포함 할 수 있습니다.
여러 줄 인수 정렬
가능하면 여러 줄 인수를 영숫자 순으로 정렬하여 나중에 쉽게 변경할 수 있습니다. 이렇게하면 패키지 중복을 방지하고 목록을 훨씬 쉽게 업데이트 할 수 있습니다. 또한 PR을 읽고 검토하기가 훨씬 쉬워집니다. 백 슬래시 (\
) 앞에 공백을 추가하는 것도 도움이됩니다.
다음은 buildpack-deps
이미지의 예입니다.
빌드 캐시 활용
이미지를 빌드 할 때 Docker는 Dockerfile
의 지침을 단계별로 수행하여 지정된 순서대로 각각을 실행합니다. 각 명령어를 검사 할 때 Docker는 새(중복) 이미지를 생성하는 대신 캐시에서 재사용 할 수 있는 기존 이미지를 찾습니다.
캐시를 전혀 사용하지 않으려면 docker build
명령에 --no-cache = true
옵션을 사용할 수 있습니다. 그러나 Docker가 캐시를 사용하도록 허용하는 경우 일치하는 이미지를 찾을 수 있는 경우와 찾을 수 없는 경우를 이해하는 것이 중요합니다. Docker가 따르는 기본 규칙은 다음과 같습니다.
이미 캐시에 있는 상위 이미지로 시작하여 다음 명령어를 해당 기본 이미지에서 파생 된 모든 하위 이미지와 비교하여 그 중 하나가 정확히 동일한 명령어를 사용하여 빌드되었는지 확인합니다. 그렇지 않으면 캐시가 무효화됩니다.
대부분의 경우
Dockerfile
의 명령어를 하위 이미지 중 하나와 비교하는 것만으로도 충분합니다. 그러나 특정 지침에는 더 많은 검사와 설명이 필요합니다.ADD
및COPY
명령의 경우 이미지에있는 파일의 내용을 검사하고 각 파일에 대해 체크섬을 계산합니다. 파일의 마지막 수정 및 마지막 액세스 시간은이 체크섬에서 고려되지 않습니다. 캐시 조회 중에 체크섬은 기존 이미지의 체크섬과 비교됩니다. 내용 및 메타 데이터와 같이 파일에서 변경된 사항이 있으면 캐시가 무효화됩니다.ADD
및COPY
명령을 제외하고 캐시 검사는 캐시 일치를 확인하기 위해 컨테이너의 파일을 확인하지 않습니다. 예를 들어RUN apt-get -y update
명령을 처리 할 때 컨테이너에서 업데이트 된 파일은 캐시 적중이 존재하는지 확인하기 위해 검사되지 않습니다. 이 경우 명령 문자열 자체 만 일치를 찾는 데 사용됩니다. 캐시가 무효화되면 모든 후속Dockerfile
명령이 새 이미지를 생성하고 캐시는 사용되지 않습니다.
Dockerfile 지침
이러한 권장 사항은 효율적이고 유지 관리 가능한 Dockerfile
을 만드는 데 도움이되도록 설계되었습니다.
FROM
가능하면 현재 공식 이미지를 이미지의 기초로 사용하세요. Alpine 이미지는 엄격하게 제어되고 크기가 작으며 (현재 5MB 미만) 전체 Linux 배포판이므로 권장합니다.
LABEL
이미지에 레이블을 추가하여 프로젝트별로 이미지를 구성하고, 라이센싱 정보를 기록하고, 자동화를 지원하거나 기타 다른 이유로 사용할 수 있습니다.
각 라벨에 LABEL
로 시작하고 하나 이상의 키-값 쌍으로 시작하는 줄을 추가합니다.
다음 예는 다양한 허용 형식을 보여줍니다. 설명 주석이 인라인으로 포함됩니다.
공백이있는 문자열은 따옴표로 묶거나 or 공백을 이스케이프 해야합니다. 내부 따옴표 (
"
)도 이스케이프해야합니다.
이미지에는 둘 이상의 레이블이있을 수 있습니다. Docker 1.10 이전에는 추가 레이어가 생성되지 않도록 모든 라벨을 단일 LABEL
명령어로 결합하는 것이 좋습니다. 더 이상 필요하지 않지만 레이블 결합은 계속 지원됩니다.
위의 내용은 다음과 같이 작성할 수도 있습니다.
허용되는 레이블 키 및 값에 대한 지침은 객체 레이블 이해를 참조하십시오. 레이블 쿼리에 대한 자세한 내용은 객체 레이블 관리의 필터링 관련 항목을 참조하십시오. Dockerfile 참조의 LABEL도 참조하세요.
RUN
길거나 복잡한 RUN
문을 백 슬래시로 구분된 여러 줄로 분할하여 Dockerfile
을 더 읽기 쉽고 이해하기 쉽고 유지 관리하기 쉽게 만듭니다.
apt-get
아마도 RUN
의 가장 일반적인 사용 사례는 apt-get
의 애플리케이션 일 것입니다. 패키지를 설치하기 때문에 RUN apt-get
명령에는 주의해야 할 몇가지 문제가 있습니다.
상위 이미지의 많은 "필수"패키지가 비 권한 컨테이너 내에서 업그레이드 할 수 없으므로 RUN apt-get upgrade
및 dist-upgrade
를 피하십시오.
부모 이미지에 포함 된 패키지가 오래된 경우 해당 관리자에게 문의하십시오.
업데이트해야하는 특정 패키지 foo
가있는 경우 apt-get install -y foo
를 사용하여 자동으로 업데이트합니다.
항상 동일한 RUN
문에서 RUN apt-get update
와 apt-get install
을 결합하십시오. 예를 들면 :
RUN
문에서 apt-get update
만 사용하면 캐싱 문제가 발생하고 후속 apt-get install
명령이 실패합니다.
예를 들어 Dockerfile이 있다고 가정합니다.
이미지를 빌드 한 후 모든 레이어는 Docker 캐시에 있습니다.
나중에 추가 패키지를 추가하여 apt-get install
을 수정한다고 가정합니다.
Docker는 초기 및 수정 된 지침을 동일하게보고 이전 단계의 캐시를 재사용합니다.
결과적으로 빌드가 캐시 된 버전을 사용하기 때문에 apt-get update
가 실행되지 않습니다.
apt-get update
가 실행되지 않기 때문에 빌드가 잠재적으로 curl
및 nginx
패키지의 오래된 버전을 가져올 수 있습니다.
RUN apt-get update && apt-get install -y
를 사용하면 Dockerfile이 추가 코딩이나 수동 개입없이 최신 패키지 버전을 설치할 수 있습니다. 이 기술을 "캐시 무효화" 라고합니다.
패키지 버전을 지정하여 캐시 무효화를 수행 할 수도 있습니다.
이를 버전 고정이라고합니다. 예를 들면 다음과 같습니다.
버전 고정은 캐시에있는 항목에 관계없이 빌드가 특정 버전을 검색하도록 합니다. 이 기술은 또한 필수 패키지의 예상치 못한 변경으로 인한 실패를 줄일 수 있습니다.
다음은 모든 apt-get
권장 사항을 보여주는 잘 구성된 RUN
명령어입니다.
s3cmd
인수는 1.1. *
버전을 지정합니다. 이미지가 이전에 오래된 버전을 사용한 경우 새 버전을 지정하면 apt-get update
캐시 버스트가 발생하고 새 버전이 설치됩니다.
각 줄에 패키지를 나열하면 패키지 복제 실수를 방지 할 수 있습니다.
또한 /var/lib/apt/lists
를 제거하여 apt 캐시를 정리하면 apt 캐시가 레이어에 저장되지 않으므로 이미지 크기가 줄어 듭니다.
RUN
구문은 apt-get update
로 시작하므로 패키지 캐시는 항상 apt-get install
전에 새로 고쳐집니다.
공식 Debian 및 Ubuntu 이미지
apt-get clean
자동 실행이므로 명시 적으로 호출 할 필요가 없습니다.
파이프 사용
일부 RUN
명령은 다음 예와 같이 파이프 문자 (|
)를 사용하여 한 명령의 출력을 다른 명령으로 파이프하는 기능에 따라 다릅니다.
Docker는 파이프에서 마지막 작업의 종료 코드만 평가하여 성공 여부를 확인하는 /bin/sh -c
인터프리터를 사용하여 이러한 명령을 실행합니다. 위의 예제에서 이 빌드 단계는 wget
명령이 실패하더라도 wc -l
명령이 성공하는 한 성공하고 새 이미지를 생성합니다.
파이프의 어느 단계에서든 오류로 인해 명령이 실패하도록하려면 set -o pipefail &&
를 앞에 추가하여 예기치 않은 오류로 인해 빌드가 실수로 성공하지 못하도록 합니다. 예를 들면 :
모든 쉘이
-o pipefail
옵션을 지원하는 것은 아닙니다.Debian 기반 이미지의
dash
쉘과 같은 경우RUN
의 실행 형식을 사용하여pipefail
옵션을 지원하는 쉘을 명시 적으로 선택하는 것이 좋습니다. 예를 들면 :
CMD
CMD
명령은 인수와 함께 이미지에 포함 된 소프트웨어를 실행하는 데 사용해야합니다.
CMD
는 거의 항상 CMD ["executable", "param1", "param2"…]
형식으로 사용되어야합니다.
따라서 이미지가 Apache 및 Rails와 같은 서비스 용인 경우 CMD ["apache2", "-DFOREGROUND"]
와 같은 것을 실행합니다.
실제로 이러한 형식의 지침은 모든 서비스 기반 이미지에 권장됩니다.
대부분의 다른 경우 CMD
에는 bash, python 및 perl과 같은 대화 형 셸이 제공되어야합니다.
예로 : CMD ["perl", "-de0"]
, CMD ["python"]
또는 CMD ["php", "-a"]
.
이 형식을 사용하면 docker run -it python
과 같은 것을 실행할 때 사용할 수있는 쉘로 이동할 준비가 된 것입니다.
CMD
는 ENTRYPOINT
와 함께 CMD ["param", "param"]
방식으로 사용해서는 안 됩니다.
사용자는 사전에 ENTRYPOINT
의 작동 방식에 대해 잘 알고 있어야 합니다.
EXPOSE
EXPOSE
명령어는 컨테이너가 연결을 수신하는 포트를 나타냅니다. 따라서 응용 프로그램에 대해 일반적인 일반 포트를 사용해야합니다.
예를 들어 Apache 웹 서버가 포함 된 이미지는 EXPOSE 80
을 사용하고 MongoDB를 포함하는 이미지는 EXPOSE 27017
등을 사용합니다.
외부 액세스를 위해 사용자는 지정된 포트를 자신이 선택한 포트에 매핑하는 방법을 나타내는 플래그와 함께 docker run
을 실행할 수 있습니다.
컨테이너 연결을 위해 Docker는 수신자 컨테이너에서 소스까지의 경로에 대한 환경 변수를 제공합니다 (예 :MYSQL_PORT_3306_TCP
).
ENV
[ENV 명령어에 대한 Dockerfile 참조] (https://docs.docker.com/engine/reference/builder/#env)
새 소프트웨어를 더 쉽게 실행하려면 ENV
를 사용하여 컨테이너가 설치하는 소프트웨어의 PATH
환경 변수를 업데이트 할 수 있습니다.
예를 들어 ENV PATH /usr/local/nginx/bin:$PATH
는 CMD ["nginx"]
가 작동하도록 합니다.
ENV
명령어는 Postgres의 PGDATA
와 같이 컨테이너화하려는 서비스에 특정한 필수 환경 변수를 제공하는데도 유용합니다.
마지막으로, ENV
는 일반적으로 사용되는 버전 번호를 설정하는데도 사용할 수 있으므로 다음 예제와 같이 버전 범프를 유지하기가 더 쉽습니다.
Similar to having constant variables in a program (as opposed to hard-coding values), this approach lets you change a single ENV
instruction to auto-magically bump the version of the software in your container.
각 ENV
라인은 RUN
명령과 마찬가지로 새로운 중간 레이어를 생성합니다.
즉, 향후 계층에서 환경 변수를 설정해제 하더라도 이 계층에서 계속 유지되며 해당 값을 덤프 할 수 없습니다.
다음과 같이 Dockerfile을 만든 다음 빌드하여이를 테스트 할 수 있습니다.
이를 방지하고 실제로 환경 변수를 설정해제 하려면 쉘 명령과 함께 RUN
명령을 사용하여 단일 레이어에서 변수를 설정, 사용 및 설정해제하십시오.
;
또는 &&
로 명령을 분리 할 수 있습니다. 두 번째 방법을 사용하고 명령 중 하나가 실패하면 docker build
도 실패합니다. 이것은 일반적으로 좋은 생각입니다.
Linux Dockerfiles의 줄 연속 문자로 \
를 사용하면 가독성이 향상됩니다.
모든 명령을 쉘 스크립트에 넣고 RUN
명령이 해당 쉘 스크립트를 실행하도록 할 수도 있습니다.
ADD or COPY
ADD
와 COPY
는 기능적으로 유사하지만 일반적으로 COPY
가 선호됩니다. ADD
보다 투명하기 때문입니다.
COPY
는 컨테이너에 로컬 파일의 기본 복사 만 지원하는 반면 ADD
에는 즉시 명확하지 않은 일부 기능 (로컬 전용 tar 추출 및 원격 URL 지원)이 있습니다.
따라서 ADD
의 가장 좋은 용도는 ADD rootfs.tar.xz /
에서와 같이 로컬 tar 파일을 이미지로 자동 추출하는 것입니다.
컨텍스트와 다른 파일을 사용하는 여러 Dockerfile
단계가 있는 경우 한 번에 모두가 아닌 개별적으로 COPY
하십시오.
이렇게하면 특별히 필요한 파일이 변경된 경우에만 각 단계의 빌드 캐시가 무효화됩니다 (단계를 다시 실행해야 함).
예를 들면 :
COPY . /tmp/
를 앞에 둔 경우보다 RUN
단계에 대한 캐시 무효화가 더 적습니다.
이미지 크기가 중요하므로 ADD
를 사용하여 원격 URL에서 패키지를 가져 오는 것은 권장되지 않습니다. 대신 curl
또는 wget
을 사용해야 합니다.
이렇게하면 더 이상 필요하지 않은 파일을 추출한 후 삭제할 수 있으며 이미지에 다른 레이어를 추가 할 필요가 없습니다.
예를 들어 다음과 같은 행위는 피해야합니다.
대신 다음과 같이하십시오.
ADD
의 tar 자동 추출 기능이 필요하지 않은 다른 항목(파일, 디렉토리)의 경우 항상 COPY
를 사용해야합니다.
ENTRYPOINT
Dockerfile reference for the ENTRYPOINT instruction
ENTRYPOINT
의 가장 좋은 용도는 이미지의 기본 명령을 설정하여 해당 이미지의 명령인 것처럼 실행되도록 허용하는 것입니다 (그런 다음 CMD
를 기본 플래그로 사용).
명령 줄 도구 's3cmd'에 대한 이미지의 예부터 시작하겠습니다.
이제 이미지를 다음과 같이 실행하여 명령의 도움말을 표시 할 수 있습니다.
또는 올바른 매개 변수를 사용하여 명령을 실행합니다.
이것은 위의 명령에 표시된대로 이미지 이름이 바이너리에 대한 참조로 두 배가 될 수 있기 때문에 유용합니다.
ENTRYPOINT
명령어는 도우미 스크립트와 함께 사용할 수도 있어, 도구를 시작하는데 두 단계 이상이 필요할 때도 위의 명령과 비슷한 방식으로 작동 할 수 있습니다.
예를 들어 Postgres 공식 이미지는 다음과 같은 스크립트를 ENTRYPOINT
로 사용한다.
앱을 PID 1로 구성
이 스크립트는
exec
Bash 명령을 사용하므로 최종 실행 애플리케이션이 컨테이너의 PID 1이 됩니다. 이를 통해 애플리케이션은 컨테이너로 전송 된 모든 Unix 신호를 수신 할 수 있습니다. 자세한 내용은ENTRYPOINT
참조를 참조하세요.
도우미 스크립트는 컨테이너에 복사되고 컨테이너 시작시 ENTRYPOINT
를 통해 실행됩니다.
이 스크립트를 통해 사용자는 여러 가지 방법으로 Postgres와 상호 작용할 수 있습니다.
간단히 Postgres를 시작할 수 있습니다.
또는 Postgres를 실행하고 매개 변수를 서버에 전달하는 데 사용할 수 있습니다.
마지막으로 Bash와 같은 완전히 다른 도구를 시작하는 데 사용할 수도 있습니다.
VOLUME
VOLUME
명령은 데이터베이스 저장소 영역, 구성 저장소 또는 Docker 컨테이너에서 생성 한 파일/폴더를 노출하는 데 사용해야합니다.
이미지의 변경 가능 하거나 사용자 서비스 가능 부분에 VOLUME
을 사용하는 것이 좋습니다.
USER
권한없이 서비스를 실행할 수 있는 경우 USER
를 사용하여 루트가 아닌 사용자로 변경하십시오.
RUN groupadd -r postgres && useradd --no-log-init -r -g postgres postgres
와 같이 Dockerfile
에 사용자와 그룹을 생성하여 시작합니다.
명시적인 UID / GID 고려
이미지의 사용자 및 그룹에는 이미지 재 구축에 관계없이 "다음" UID/GID가 할당된다는 점에서 비 결정적 UID/GID가 할당됩니다. 따라서 중요한 경우 명시적인 UID/GID를 할당해야합니다.
Go 아카이브/tar 패키지의 빈약한 파일 관리에서 해결되지 않은 버그로 인해 Docker 컨테이너 내에 상당히 큰 UID를 가진 사용자를 만들려고하면 컨테이너 계층의
/var/log/faillog
가 NULL(\0) 문자로 채워집니다. 해결 방법은--no-log-init
플래그를 useradd에 전달하는 것입니다. Debian/Ubuntuadduser
명령어는 이 플래그를 지원하지 않습니다.
예측할 수없는 TTY 및 신호 전달 동작이 문제를 일으킬 수 있으므로 sudo
를 설치하거나 사용하지 마십시오.
root
가 아닌 사용자로 실행하지만 데몬을 root
로 초기화 하는 등 sudo
와 유사한 기능이 절대적으로 필요한 경우 "gosu" 사용을 고려하세요.
마지막으로 레이어와 복잡성을 줄이려면 USER
를 자주 앞뒤로 전환하여 사용하지 마십시오.
WORKDIR
명확성과 신뢰성을 위해 항상 WORKDIR
에 절대 경로를 사용해야합니다.
또한 읽기, 문제 해결, 유지 관리가 어려운 RUN cd… && do-something
과 같은 명령을 확산시키는 대신 WORKDIR
을 사용해야합니다.
ONBUILD
ONBUILD
명령은 현재 Dockerfile
빌드가 완료된 후 실행됩니다.
ONBUILD
는 현재 이미지의 FROM
에서 파생 된 모든 하위 이미지에서 실행됩니다.
ONBUILD
명령을 부모 Dockerfile
이 하위 Dockerfile
에게 제공하는 명령으로 생각하십시오.
Docker 빌드는 하위 Dockerfile
의 명령보다 먼저 ONBUILD
명령을 실행합니다.
ONBUILD
는 주어진 이미지에서 FROM
으로 빌드 될 이미지에 유용합니다.
예를 들어 Ruby의 ONBUILD
변형에서 볼 수 있듯이 Dockerfile
내에서 해당 언어로 작성된 임의 사용자 소프트웨어를 빌드하는 언어 스택 이미지에 ONBUILD
를 사용합니다.
ONBUILD
로 빌드 된 이미지는 별도의 태그를 가져야합니다 (예 : ruby:1.9-onbuild
또는 ruby:2.0-onbuild
).
ONBUILD
에 ADD
또는 COPY
를 넣을 때 주의하세요.
새 빌드의 컨텍스트에 추가되는 리소스가 누락 된 경우 "onbuild" 이미지가 처참히 실패합니다.
위에서 권장했던로 별도의 태그를 추가하면 Dockerfile
작성자가 선택할 수 있도록하여 이를 완화하는 데 도움이됩니다.
공식 이미지의 예
이 공식 이미지에는 대표적인 Dockerfile
이 있습니다.
추가 리소스 :
Last updated
Was this helpful?