용찬호. 「 시작하세요! 도커/쿠버네티스」. 위키북스 를 읽으며, 학습한 내용을 정리하는 글입니다.
→ 본문의 내용은 모두 책의 내용에 대한 직/간접적 인용임을 밝힙니다.
[ 기존의 가상화 기술 ]
[ 기존 기술의 한계 ]
→ 가상 머신은 완벽한 운영체제를 생성할 수 있지만 일반 호스트에 비해 성능 손실
→ 기가바이트 단위인 가상 머신 이미지를 애플리케이션으로 배포하기는 부담
[ 도커 ]
attach
: 컨테이너 내부로 들어가는 명령어ifconfig
명령어로 네트워크 인터페이스 확인 가능.→ 외부에 컨테이너 애플리케이션을 노출하기 위해, eth0의 IP와 포트를 호스트의 IP와 포트에 바인딩해야 함!
cf. eth0 은 무엇일까?
https://seosh817.tistory.com/373#google_vignette
** 한 컨테이너에 프로세스 하나만 실행하는 게 도커의 철학이다 p.35
[ #1. 2.2.6.1 호스트와 볼륨 공유하기 ]
/home/workdpress_db:/var/lib/mysql
-> 호스트의 디렉토리와 컨테이너의 디렉토리를 공유한다는 뜻!
-> "동기화"되는 것이 아니라 완전히 같은 디렉터리이다.
< cf. 호스트에 이미 디렉터리, 파일 존재하고 컨테이너에도 존재하면 ? >
[ #2. 2.2.6.2 볼륨 컨테이너 ]
--volumes-from
옵션을 설정하면 -v, --volume 옵션을 적용한 컨테이너의 볼륨 디렉터리를 공유할 수 있다.docker run -i -t \
--name volumes_from_container \
--volumes-from volume_override \
ubuntu:14.04
[ #3. 2.2.6.3 도커 볼륨 ]
docker volume
명령어를 사용하는 방식[볼륨의 이름]:[컨테이너의 공유 디렉터리]
docker run -i -t --name myvolume_1 \
-v myvolume:/root/ \
ubuntu:14.04
볼륨을 컨테이너의 /root/ 디렉터리에 마운트하므로, /root 디렉토리에 파일을 쓰면 해당 파일이 볼륨에 저장된다.
cf. docker inspect --type volume myvolume
등으로 정보를 확인할 수 있음!
컨테이너의 네트워크 인터페이스에는 eth0과 lo 네트워크 인터페이스가 있다.
ifconfig
eth0
: 공인 IP 또는 내부 IP가 할당되어, 실제로 외부와 통신 가능한 호스트의 네트워크 이인터페이스 veth...
: 컨테이너 시작 시 생성되어, 각 컨테이너의 eth0
과 연결된다.cf. docker0
브릿지 : 각 veth 인터페이스와 바인딩되어, 호스트의 eth0
인터페이스와 이어주는 역할을 한다~!
[ 2.2.7.2 도커 네트워크의 기능 ]
도커가 자체적으로 지원하는 네트워크 드라이버
→ bridge, host, none, container, overlay
docker0
브릿지를 활용하도록 설정됨veth
가상 네트워크 인터페이스도 만들어지지 않는다. cf. docker logs
옵션
--tail
: 마지막 로그부터 출력할 줄 수를 지정--since
: 특정 유닉스 시간 이후의 로그 출력-t
: 타임스탬프 표시 가능-f
: 로그를 스트림으로 확인 가능docker run --log-opt
옵션을 통한 로그 파일 옵션
max-size
: 로그 파일의 최대 크기max-file
: 로그 파일의 개수cf. [ AWS Cloudwatch Logs ]
1. 클라우드워치에 해당하는 IAM 권한 생성하기
2. 로그 그룹 생성하기
3. 로그 그룹에 로그 스트림 생성
4. IAM 권한을 사용할 수 있는 EC2 인스턴스 생성과 로그 전송
--memory
: 컨테이너의 메모리 제한 (최소 4MB)--cpu-shares
: 컨테이너에 가중치 설정하여 CPU를 상대적으로 얼마나 쓸 수 있는지 명시cf. docker search
→ 도커 허브에서 이미지를 검색한다.
[ 주요 명령어 ]
FROM
: 생성할 이미지의 베이스가 될 이미지MAINTAINER
: 이미지를 생성한 개발자의 정보. 도커 1.13.0 버전 이후로 사용되지 않는다.LABEL
: 이미지에 추가하는 메타데이터LABEL maintainer "alicek106 <alicek@naver.com>
같이 사용RUN
: 이미지를 만들기 위해 컨테이너 내부에서 명령어를 실행. RUN ["실행 가능한 파일", "명령줄 인자1", "명령줄 인자2"]
["sh", "-c", "echo $MY_ENV"]
ADD
: 파일을 이미지에 추가. 추가하는 파일은 Dockerfile이 위치한 디렉터리인 컨텍스트(Context)
에서 가져온다. WORKDIR
: 명령어를 실행할 디렉터리. 배시 셸의 cd
명령어와 같다!EXPOSE
: Dockerfile의 빌드로 생성된 이미지에서 노출할 포트 설정CMD
: 컨테이너가 시작될 때마다 실행할 명령어를 설정하며, Dockerfile에서 한 번만 사용 가능하다.[ 예시 Dockerfile ]
FROM ubuntu:14.04 // 베이스 이미지 설정
MAINTAINER alicek106 // maintainer의 이름 설정
LABEL "purpose"="practice" // 이미지의 라벨을 설정
RUN apt-get update
RUN apt-get install apache2 -y // 명령어 실행하여 apache 웹서버 설치
ADD test.html /var/www/html // Dockerfile이 위치한 디렉터리에서 text.html 파일을, 이미지의 /var/www/html 디렉터리에 추가
WORKDIR /var/www/html // 작업 디렉터리 설정
RUN ["/bin/bash", "-c", "echo hello >> test2.html"] // 옮긴 작업 디렉터리에 파일 생성
EXPOSE 80 // 컨테이너가 사용할 포트 지정
CMD apachectl -DFOREGROUND
docker build -t mybuild:0.0 ./
mybuild:0.0
이라는 이름으로, 현재 위치(./)의 Dockerfile을 빌드!
docker run -d -P --name myserver mybuild:0.0
-P
: 이미지에 설정된 EXPOSE의 모든 포트를 호스트에 연결하도록 설정docker port myserver
→ 컨테이너와 연결된 호스트의 포트를 확인한다.
docker images --filter ="label=purpose=practice"
→ 라벨로 필터링된 이미지만을 출력!
[ 2.4.3.2 빌드 과정 살펴보기 ]
dockerignore
파일을 사용하여 특정 파일을 컨텍스트에서 제외하자!cf. .dockerignore
예시
test2.html
*.html // 현재_디렉터리/*.html 제외
*/*.html // 현재_디렉터리/*/*.html // 한 디렉터리 레벨 거침
test.htm? // ?자리에 임의의 한 문자
!test.html // test.html은 제외하지 않는다!
[ Dockerfile을 이용한 생성과 커밋 ]
ADD
, RUN
등 명령어가 실행될 때마다, 새로운 컨테이너가 하나씩 생성되며 이를 이미지로 커밋한다.[ 2.4.3.3 멀티 스테이지를 이용한 Dockerfile 빌드 ]
하나의 Dockerfile 안에 여러 개의 FROM 이미지를 정의하여,
빌드 완료 시 최종적으로 생성될 이미지의 크기를 줄이는 역할을 하는 것
[ 예시 ]
FROM golang
ADD main.go /root
WORKDIR /root
RUN go build -o /root/mainApp /root/main.go
FROM alpine:latest
WORKDIR /root
COPY --from=0 /root/mainApp .
CMD ["./mainApp"]
--from=0
은 첫 번째 FROM에서 빌드된 이미지의 최종 상태를 의미한다!ENV
: Dockerfile에서 사용될 환경변수를 지정한다. VOLUME
: 빌드된 이미지로 컨테이너를 생성했을 때 호스트와 공유할 컨테이너 내부의 디렉터리를 설정합니다. ARG
: build 명령어를 실행할 때, 추가로 입력을 받아 Dockerfile 내에서 사용될 변수의 값을 설정합니다.FROM ubuntu:14.04
ARG my_arg
ARG my_arg_2=value2
RUN touch ${my_arg}/mytouch
→ docker build --build-arg my_arg=/html -t myarg:0.0 ./
→ build 시점에 ARG를 지정!
USER
: 컨테이너 내에서 사용될 사용자 꼐정의 이름이나 UID를 설정하면, 그 아래의 명령어는 해당 사용자 권한으로 실행된다.[ USER 사용 예시 ]
RUN groupadd -r author && useradd -r -g author alicek106
USER alicek106
ONBUILD
: 빌드된 이미지를 기반으로 하는 다른 이미지가 Dockerfile로 생성될 때, 실행할 명령어를 추가합니다. STOPSIGNAL
: 컨테이너가 정지될 때 사용될 시스템 콜의 종류를 지정합니다. HEALTHCHECK
: HEALTHCHECK는 이미지로부터 생성된 컨테이너에서 동작하는 애플리케이션의 상태를 체크하도록 설정합니다. SHELL
: 사용하려는 셸을 따로 지정SHELL ["/usr/local/bin/node"]
COPY
: 로컬 디렉터리에서 읽어들인 컨텍스트로부터 이미지에 파일을 복사하는 역할ADD
는 외부 URL 및 tar 파일에서도 파일 추가가 가능하다는 차이!COPY
가 권장된다![ 2.4.4.4 ENTRYPOINT, CMD ]
< ENTRYPOINT와 CMD의 차이점 >
docker run -i -t --name no_entrypoint ubuntu:14.04 /bin/bash
→ entrypoint 없음
→ cmd : /bin/bash
docker run -i -t --entrypoint="echo" --name yes_entrypoint ubuntu:14.04 /bin/bash
/bin/bash
→ entrypoint : echo
→ cmd : /bin/bash
=> entrypoint가 설정되면, run 명령어의 마지막에 입력된 cmd를 인자로 삼아 명령어를 출력한다.
=> echo /bin/bash가 된 것!
[ JSON 배열 형태와 일반 형식의 차이점 ]
/bin/sh -c
가 추가되기 때문![ 잘못된 사용 방식 ]
FROM ubuntu:14.04
RUN mkdir /test
RUN fallocate -l 100m /test/dummy
RUN rm /test/dummy
→→ Dockerfile 작성 시에 &→으로 각 RUN 명령을 하나로 묶자.
→→ RUN 하나가 하나의 이미지 레이어이므로!
도커는 실제로 어디에 있을까?
which docker
// /usr/bin/docker
실행 중인 도커 프로세스 확인
ps aux | grep docker
..... /usr/bin/dockerd -H fd://
→ 컨테이너나 이미지를 다루는 명렁어는 /usr/bin/docker
에서 실행되지만, 도커 엔진의 프로세스는 /usr/bin/dockerd
파일로 실행된다.
→ 이는 docker 명령어가 실제 도커 엔진이 아닌, 클라이언트로서의 도커이기 때문!
[ 도커 서버 ]
[ 도커 클라이언트 ]
/var/run/docker.sock
에 위치한 유닉스 소켓을 통해 도커 데몬의 API를 호출한다. [ docker 명령어 입력할 때의 과정 ]
1. 사용자가 docker ps
같은 명령어를 입력
2. /usr/bin/docker
는 /var/run/docker.sock
유닉스 소켓을 사용해 도커 데몬에게 명령어를 전달
3. 도커 데몬은 이 명령어를 파싱하고, 해당하는 작업을 수행
4. 수행 결과를 도커 클라이언트에게 반환하고, 사용자에게 결과를 출력.
우분투에서는 도커가 설치되면 자동으로 서비스로 등록된다!
service docker start
service docker stop
service docker stop // 도커 서비스를 정지한 뒤
dockerd // 명령어로 직접 도커를 실행하는 방식
...
...
// API listen on /var/run/docker.sock
dockerd --help
[ 2.5.3.1 도커 데몬 제어: -H ]
dockerd
dockerd -H unix:///var/run/docker.sock // 도커 클라이언트 /usr/bin/docker를 위한 유닉스 소켓 /var/run/docker.sock
dockerd -H tcp://0.0.0.0:2375
→ remote API를 위한 바인딩 주소를 입력하면 유닉스 소켓은 비활성화
→ 도커 클라이언트를 사용할 수는 없어진다 (docker ~ 명령어 사용 불가)
→ 일반적으로, 아래와 같이 도커 클라이언트를 위한 유닉스 소켓과 Remote API를 위한 바인딩 주소를 동시 설정
dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2375
[ 2.5.3.3 도커 스토리지 드라이버 변경 : --storage-driver ]
< cf. 스토리지 드라이버의 원리 >
cf. 스냅숏(snapshot)은 "원본 파일은 읽기 전용으로 사용하되 이 파일이 변경되면 새로운 공간을 할당한다"는 개념!
→ 애플리케이션이 스냅숏의 A 파일에 쓰기 작업을 수행해야 한다면,
원본 파일을 유지하면서도 변경사항을 저장할 수 있어야 한다.
→ 이를 해결하는 방식에 따라 CoW, RoW로 나뉨!
< CoW >
< RoW >
[ 2.5.4.2 events, stats, system df 명령어 ]
docker events
docker system events
→ 도커 데몬이 수행한 명령어의 결과를 실시간으로 보여줌!
docker stats
→ 실행 중인 모든 컨테이너의 자원 사용량을 스트림으로 출력!
docker system df
→ 도커에서 사용하고 있는 이미지, 컨테이너, 로컬 볼륨의 총 개수 및 사용 중인 개수, 크기, 삭제함으로써 확보 가능한 공간을 출력.