Dockerfile 작성 시 유의사항 2 - 도커 이미지 크기가 커지지 않도록 유의
1. 레이어 최소화의 필요성
- Dockerfile의 각 라인은 레이어 형태로 이미지에 저장되므로, 지시문(명령문)을 결합해서 최적화하는 것이 필요하다.
1) 명령어마다 RUN 지시문을 사용하는 경우
2) 여러 명령어를 하나의 RUN 지시문으로 묶어 기술
2. 불필요한 도구 설치 금지
- 앱 실행과 관련 없는 도구 (개발도구, 디버깅도구)와 패키지의 종속성을 제거한다.
1) --no-install-recommends 플래스 사용
- apt-get install 시 추천(recommended) 또는 제안(suggested) 패키지가 자동으로 설치되는 것을 방지하는 옵션이다.
2) 이미지 빌드
3. 빌더 패턴과 다단계 도커 빌드
1) 불필요한 아티팩트와 런타임을 포함하는 예
- Go 컴파일러는 앱 빌드할 때는 필요하지만, 실행할 때는 필요하지 않음!
=> 단순하게 Hello World 를 출력하는 데 있어 image golang의 837MB라는 용량은 불필요한 것.
2) 소스코드 빌드를 위한 이미지와 실행을 위한 이미지를 따로 만들 것!
3) 빌드 패턴을 사용한다.
4) 다단계 도커 빌드를 사용한다.
* 가독성 향상을 위해 AS 구문을 사용해 별칭을 부여할 수 있다.
Dockerfile 주요 명령어
1. RUN
: 이미지를 만들기 위해 컨테이너 내부에서 실행할 명령어
- 사용자 입력을 요구하는 명령어가 들어가면 docker image build 시 오류가 발생한다.
2. RUN, CMD, ENTRYPOINT 구문에서 명령어를 기술하는 방법
1) shell Form
예) CMD go run /myapp/main.go
형식 : INSTRUCTION command param1 param2
- 명령어(command)를 /bin/sh -c 구문을 통해서 실행한다.
=> 쉘이 먼저 실행되고, 해당 쉘에서 명령어가 실행됨을 의미한다.
- 쉘을 기본적으로 사용학 때문에 쉘이 제공하는 파이프, 리다이렉션, 변수 사용 등이 가능하다.
- CMD command_string 구문은 CMD ["/bin/sh", "-c", "command_string"] 구문과 동일하게 처리된다.
- Shell 구문을 이용하면 다른 쉘도 사용이 가능하다.
예) SHELL ["/bin/bash", "-c"]
RUN echo hello
=> /bin/sh 이 아닌 /bin/bash 을 통해서 실행
2) exec Form (권장)
예) CMD ["go", "run", "/myapp/main.go"]
형식 : INSTRUCTION ["executable", "param1", "param2"]
RUN, CMD, ENTRYPOINT
- 쉘을 통하지 않고, 명령어가 직접 실행되도록 하는 방식으로,
명령어와 인자를 JSON 배열 형식(단어를 반드시 쌍따옴표로 묶어서 표현)으로 전달한다.
- 쉘을 통하지 않기 때문에, 쉘이 제공하는 부가 기능(파이프, 리다이렉션, 변수 사용 등)을 사용할 수 없다.
=> RUN ["echo", "$HOME"] = HOME이라는 실행파일을 열어라
- 쉘을 이용해서 명령어를 실행하려고 하면, exec 형식으로 직접 쉘을 실행해야 한다!
=> RUN ["sh", "-c", "echo $HOME"] = 쉘의 HOME 환경 변수를 실행해라
3. COPY vs ADD
1) COPY
: 호스트의 로컬의 파일만 이미지에 추가할 수 있다.
2) ADD
: 외부 URL 및 tar 파일에서도 파일을 추출하여 이미지에 추가할 수 있다.
(tar 파일의 경우 자동으로 묶음을 해제해서 추가한다.)
- 의도하치 않은 파일의 추가를 방지하기 위해 COPY 사용을 권장한다.
4. WORKDIR
: 지정한 디렉터리로 전환(이동)하는 명령어이다.
- WORKDIR 명령문 이후에 등장하는 모든 RUN, CMD, ENTRYPOINT, COPY, ADD 명령문은 해당 디렉터리(WORKDIR)를 기준으로 실행한다.
5. EXPOSE (-P 옵션, 대/소문자 주의)
: 이미지에서 노출할 포트를 설정하는 명령어
예)
c:\docker\webserver> docker container run -p 9999:80 -d --name myweb2 --rm mywebserver
bbf5c12fac22308224d293983877e9de14584749881f1a130aa0e8e009416f1b
docker: Error response from daemon: driver failed programming external connectivity on endpoint myweb2 (bd1d11840fc43632dc63b3d1360bb1e0787630bb42e781320a1b827815cce4c3): Bind for 0.0.0.0:9999 failed: port is already allocated.
=> 해당 오류는 호스트 포트가 충돌해서 컨테이너가 실행되지 않음을 의미한다.
- 호스트 포트의 충돌을 방지하기 위해 호스트 포트를 지정하지 않는다.
=> 이 때 가용한 임의의 포트가 할당된다.
예)
c:\docker\webserver> docker container run -p 80 -d --name myweb2 --rm mywebserver
387c6203b1af4b1490aca6b6195192ab232f20abccd1a07506807708dd55f4e7
c:\docker\webserver> docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
387c6203b1af mywebserver "/bin/sh -c 'apachec…" 4 seconds ago Up 3 seconds 0.0.0.0:58317->80/tcp myweb2
e6b1be0d9511 mywebserver "/bin/sh -c 'apachec…" 38 minutes ago Up 38 minutes 0.0.0.0:9999->80/tcp myweb
- 컨테이너 실행 시 -P 옵션을 사용하면 호스트의 가용한 포트와 컨테이너 내부에 EXPOSE된 포트를 자동으로 매핑한다.
- 포트 맵핑 정보를 확인할 때는 docker container port 명령어를 사용하면 된다.
6. CMD vs ENTRYPOINT
- ENTRYPOINT가 설정되지 않았다면 CMD에 설정된 명령어를 그대로 실행하지만,
ENTRYPOINT가 설정되어 있다면 CMD는 단지 ENTRYPOINT에 대한 인자의 기능을 수행할 뿐이다.
- ENTRYPOINT를 사용하는 이유는 명령어로 입력한 값의 내용이 변경되는 것을 희망하지 않을 때 사용한다.
7. ENV
: Dockerfile에서 사용할 환경 변수를 지정하는데 사용한다.
- 형식 : ENV 환경변수이름=환경변수값. 설정한 환경변수는 ${환경변수이름} 또는 $환경변수이름 형태로, Dockerfile, 이미지, 이미지로 생성한 컨테이너에서 사용이 가능하다.
- docker container run 명령의 -e 옵션을 이용해서 같은 이름의 환경변수 값을 덮어 쓸 수 있다.
8. VOLUME
: Union File System을 사용하지 않고 호스트에 저장하는 명령어이다.
- -v 옵션을 이용해서 데이터 볼륨을 맵핑하면 persistant 하게 볼륨을 유지할 수 있다.
=> 컨테이너와 컨테이너 간의 데이터 공유 및 유지가 가능해진다.
Dockerfile 모범 사례
: 도커 이미지 빌드 시간 단축, 이미지 크기 감소, 보안 강화 및 유지 관리 가능성 보장하는 Dockerfile이 권장된다.
1. 적절한 베이스 이미지 사용
1) 도커 허브 공식 이미지 사용
: 도커 허브의 공식 이미지는 모범 사례를 따르고 문서화되어 있으며 보안 패치가 적용되어 있다.
2) 특정 버전의 태그 사용
: 프로덕션 환경을 위한 도커 이미지를 빌드할 때 베이스 이미지에 latest 태그를 사용하면,
하위 호환성을 제공하지 않을 경우 문제가 될 수 있다.
3) 최소 크기의 이미지를 사용
: 최소 크기 버전의 부모 이미지를 사용해야 한다. (= 최소 크기의 도커 이미지를 생성)
- Alpine Linux 이미지를 중심으로 빌드된 최소 크기 이미지 또는 빌드 도구가 포함된
JDK 대신 JRE를 사용하여 앱을 실행한다.
2. 루트가 아닌 사용자로 컨테이너 실행
: 도커 컨테이너는 기본적으로 루트(id=0) 사용자로 실행된다.
이는 해커가 도커 컨테이너 내부에서 실행되는 앱을 해킹 후 도커 호스트에 대한 루트 액세스 권한을 획득할 수 있다.
프로덕션 환경에서 루트 사용자로 도커 컨테이너를 실행하는 것은 나쁜 보안 관행으로 간주된다.
따라서 응용 프로그램 실행에 필요한 최소한의 권한만 갖도록 최소 권한의 원직을 준수해야 한다.
1) --user(또는 -u) 플래그 사용
2) USER 지시문 사용
빌드 컨텍스트 (Build Context)
: 도커 이미지를 생성하는데 필요한 각종 파일, 소스 코드, 메타 데이터 등을 담고 있는 디렉터리이다.
Dockerfile, dockerignore 등
ignore 파일 : 해당 파일에 명시된 이름의 파일을
빌드할 때 컨테스트에서 제외
빌드패턴?
*alpine : 경량 리눅스 배포판
'Study > seSAC 금천 4기' 카테고리의 다른 글
| 컨테이너 Orchestration_1일차_240924 (0) | 2024.09.30 |
|---|---|
| 컨테이터 애플리케이션 개발_4일차_240923 (0) | 2024.09.30 |
| 컨테이너 애플리케이션 개발_2일차_240919 (0) | 2024.09.30 |
| 컨테이너 애플리케이션 개발_1일차_240912 (1) | 2024.09.26 |
| 네트워크 및 시스템 관리_1일차_240910 (0) | 2024.09.25 |