Docker란?
- 컨톄이너를 실행하기 위한 실행 환경(컨테이너 런타임) 및 툴킷이다.
- 쿠버네티스의 경우 도커 이외의 컨테이너 런타임도 지원
Docker Container란?
- 도커 이미지를 기반으로 실행되는 프로세스
장점 1. 이식성이 높다.
- 도커 이미지 -> 환경의 영향을 받지 않고 다양한 환경에서 컨테이너를 기동 가능
- BORA(Build Once Run Anywhere) 콘셉트
장점 2. 가상머신에 비해 가볍다.
- '가상머신에 비해 가볍다.' , '시작과 중지가 빠르다.' 등의 장점이 있다.
- 가상머신 -> 하이퍼 바이저를 이용하여 게스트 OS를 동작시킴
- 도커 컨테이너 -> 호스트 머신의 커널을 이용하면서 네임스페이스 분리와 cgroups를 이요한 제어를 통해 독립적은 OS와 같은 환경을 만듦
- 따라서 게스트 OS 기동을 기다릴 필요 없이 프로세스를 빠르게 시작 및 중지 가능
Docker Container 설계
도커 컨테이너 설계 주의사항
- 하나의 컨테이너당 하나의 프로세스 -> 가장 중요
- 이를 무시할 경우 관리에 어려움이 발생할 수 있음 - 변경 불가능한 인프라(Immutable Infrastructure) 이미지로 생성
- 이미지 안에 실행 애플리케이션, 바이너리 및 관련 리소스를 가능한 포함시켜야 함g
- 외부 다운로드, 패키지 설치 권장 x - 최대한 경량 도커 이미지로 생성
- 이미지 외부 레포지토리 다운로드를 해야하는 경우가 발생할 수 있기 때문
- yum, apt 패키지 설치 후 저장소 패키지 목록 등의 캐시 파일을 삭제하는 방법, 경량 베이스 이미지 사용 등의 방법이 있다. - 실행 계정은 root 이외의 사용자로 설정
- 보안 취약점 발생할 수 있음
Dokcerfile 작성법
다음은 HTTP 요청이 오면 'Hello Kubernetes' 라고 응답하는 Go 언어 애플리케이션(main.go)을 실행하는 컨테이너 이미지 생성 예시 Dockerfile이다.
# Alpine 3.7 버전 golang 1.10.1 이미지를 사용
FROM golang:1.10.1-alpine3.7
# 8080 포트 오픈
EXPOSE 8080
# 빌드할 머신에 있는 main.go 파일을 컨테이너에 복사
COPY ./main.go ./
# 컨테이너 내부에서 명령어 실행
RUN go build -o ./go-app ./main.go
# 실행 계정을 nobody로 변경
USER nobody
# 컨테이너가 기동할 때 실행할 명령어 정의
ENTRYPOINT ["./go-app"]
- FROM : 컨테이너 이미지에서 기반이 되는 이미지를 지정(Base Image)
- RUN, COPY 명령을 사용하여 패키지 설치 및 파일 복사 등을 처리
- ENTRYPOINT , CMD 는 컨테이너가 기동할 때 실행하는 명령어를 지정
- e.g ENTRYPOINT /bin/sleep , CMD 3600 으로 설정하면 "/bin/slepp 3600" 명령어가 컨테이너 기동 시 수행된다.
- ENTRYPOINT 는 기본적으로 변경할 필요 없는 부분을 정의하고, CMD는 인수를 지정하여 나중에 변경하여 실행할 수 있다.
Dockerfile에서 사용 가능한 명령 리스트
명령 | 요약 |
FROM | Base Image 지정 |
MAINTAINER | 컨테이너 이미지 관리자 정보 기입 (현재는 비추천, 아래의 LABEL을 주로 사용) |
LABEL | 컨테이너 이미지 메타데이터를 key:value 형식으로 기입 (e.g. LABEL maintainer="Song Hyunjoon<thdguswns31@gmail.com>") |
USER | 명령어 실행 계정 지정 |
WORKDIR | 명령어를 실행할 작업 디렉터리 설정, 디렉터리가 없을 경우 생성 |
EXPOSE | 컨테이너 실행 시 Listen할 포트 설정 |
COPY | 로컬에 있는 파일을 컨테이너로 복사 |
ADD | 로컬에 있는 tar.gz 파일을 압축 해제하여 컨테이너로 복사 |
RUN | 컨테이너 안에서 명령어를 실행 |
ENTRYPOINT | 컨테이너 기동 시에 실행할 명령어 |
CMD | 컨테이너 기동 시에 실행할 명령 인수 |
대표적인 Base Image 리스트
이미지명 | 이미지 사이즈 |
scratch | 최소 |
alpine | 작다 |
distroless | 작다 |
ubuntu | 크다 |
centos | 크다 |
Universal Base Image | 크다 |
- scratch는 쉘을 포함하여 이미지 내에 아무것도 설치되어 있지 않다.
- alpine 리눅스는 musl libc와 busybox 기반으로 한 경량 리눅스이다.
- distroless 는 python, node.js 등 특정 애플리케이션 런타임만 포함된 이미지이다.
- Universal Base Image는 RedHat의 기술지원을 필요로할 때 사용
Docker Image Build
위의 예시에 작성한 Dockerfile을 로컬 PC에서 빌드해보았다.
docker image build -t sample-image:0.1 .
- -t 옵션으로 이미지 이름 및 태그를 지정할 수 있다. (이미지이름:태그)
- 명령어 마지막에 오는 "." 은 반드시 존재해야하며 현재 경로의 Dockerfile을 자동으로 빌드하게된다.
이미지 빌드 후 생성된 이미지를 확인해보면 다음과 같다.
docker image ls
멀티 스테이지 빌드
방금 생성한 도커 이미지는 golang:1.14.1-alpine3.11 을 Base Image로 사용하였다. golang:1.14.1-alpine3.11 또한 alpine(5.6MB)를 Base Image로 하여 만들어진 본래 아주 작은 이미지이지만 golang 이미지에는 GO 컴파일 도구 등 약 346MB가 추가로 포함되어 있다. 즉 위에서 생성한 sample-image:0.1 에도 동일하게 해당 컴파일 도구가 포함되어 이미지 사이즈가 매우 커진다.
이를 해결하기 위한 방법이 멀티 스테이지 빌드이다.
- 여러 컨테이너 이미지를 사용하여 처리 후 결과물만 실행용 컨테이너로 전달
- sample-image:0.1 에서 Golang 이미지는 애플리케이션 컴파일에 필요한 도구로만 사용되며 결과물을 실행할 때는 필요하지 않다.
# Stage 1 컨테이너(애플리케이션 빌드)
FROM golang:1.10.1-alpine3.7 as builder
COPY ./main.go ./
RUN go build -o /go-app ./main.go
# Stage 2 컨테이너(빌드된 바이너리를 포함한 실행용 컨테이너 생성)
FROM alpine:3.7
EXPOSE 8080
# Stage 1에서 빌드된 결과물을 복사
COPY --from=builder /go-app .
USER nobody
ENTRYPOINT ["./go-app"]
햬당 과정을 그림으로 표현하면 다음과 같다
실제로 그럼 도커 이미지 빌드 테스트를 통해 결과를 비교해보면 다음과 같은 결과를 얻는다.
$ docker image build -t image-smaple:0.2 -f Dockerfile-MultiStage .
$ docker image ls
위와 같이 빌드된 이미지의 용량을 대폭 줄일 수 있게 된다.
도커 이미지 업로드
도커 이미지는 도커 레지스트리라는 원격 저장소에 업로드 가능하다. 대표적으로 Docker Hub, Google Container Registry(GCR), Amazon Elastic Container Registry(ECR) 등이 있다.
도커 이미지를 실제로 Docker Hub 에 업로드 해보면 다음과 같이 진행된다.
# 도커 허브 계정 생성 후 로그인
$ docker login
Username , Password 입력
# 이미지 태그명 변경
$ docker image tag sample-image:0.1 thdguswns31/sample-image:0.1
thdguswns31 -> 도커 허브 유저이름(DOCKERHUB_USER)이다.
# 도커 허브에 이미지 업로드
$ docker image push thdguswns31/sample-image:0.1
컨테이너 기동
도커 컨테이너를 기동시키려면 아래와 같이 진행하면 된다. 다만 쿠버네티스를 사용하는 경우 아래와 같이 직접 컨테이너를 기동시킬 일은 없을 것이다.
# 도커 컨테이너 기동(localhost:12345 로 접속하면 8080/TCP 포트로 포트포워딩 되어 컨테이너 애플리케이션에 접근)
$ docker run -d -p 12345:8080 sample-image:0.1
# 배포된 컨테이너 조회
$ docker ps -a
# 배포한 애플리케이션 동작 확인
$ curl http://localhost:12345
# 도커 컨테이너 제거
$ docker rm -f {Container ID}
여기까지 쿠버네티스를 공부하기 전 기본적으로 알아야하는 도커 컨테이너에대해 정리해보았다.
이어서 다음 포스트부터는 쿠버네티스에대해 본격적으로 정리할 예정이다.
'k8s' 카테고리의 다른 글
[Helm 작성하기 (1)] Helm 차트 구조 (0) | 2023.02.03 |
---|---|
쿠버네티스 완벽 가이드 2장 : 쿠버네티스 특징 간단히 알아보기 (1) | 2023.02.02 |
Kubernetes Resource Summary (2) (0) | 2022.10.25 |
Kubernetes Resource Summary (1) (0) | 2022.10.24 |
CKA 준비 (30) Network Policy (1) | 2022.09.25 |