Docker
소스코드 배포처럼 어플리케이션을 개발, shipping하고 실행한다.
cpu와 운영체제에 독립적으로 운영하는것을 지향점으로 한다.
한번만든 프로그램을 모든 플랫폼에서 빠르게 실행할 수 있다.
개발이후 production으로 실행하는 과정이 빨라진다. (A.K.A DevOps)
도커파일은 어떤 OS버전을 사용하고 명령어를 수행하라는 내용을 포함하는 IaC이다.
도커파일을 통해서 environment independent한 immutable infrastructure를 구현할 수 있다.
밑단에서부터 필요한 개발도구, 라이브러리, 환경변수 등을 작성하고 도커파일을 토대로 빌드를 수행하면
그 결과로 컨테이너 이미지를 얻는다. 컨테이너 이미지는 code, runtime, library, 환경변수등을 전부 포함한다.
컨테이너는 이미지의 runtime instance이다
docker build를 수행하면 docker image를 생성한다
이미지를 run으로 실행하면 컨테이너가 된다.
컨테이너는 컴퓨터의 메모리를 점유하는 프로세스 형태이다.
docker hub에는 최적화된 official 컨테이너 이미지들이 올라와있고 라이브러리처럼 가져다 사용할 수 있다.
도커에서는 소스코드처럼 build, push,pull등의 용어를 사용한다. 소스코드를 빌드하듯이 이미지를 빌드하고 그 이미지를 registry인 docker hub에 올리고 받아와서 사용하는 IaC의 절차는 소스코드를 사용하는 과정과 비슷하다.
도커는 go로 작성된 프로그램이다.
컨테이너들이 독립적으로 동작해서 VM처럼 느껴진다. 컨테이너에게 process, 네트워크, 파일시스템 등을 합쳐서 dedicated된 것과 같은 workspace를 namespace라고 제공해준다.
control group = 엑세스권한
컨테이너간에 서로 엑세스는 금지
하드웨어 자원 논리적인 자원 등도 가상화시켜서 control가능하게 할건지를 개발자가 지정한다.
따라서 개발자 입장에서는 vm과 차이가 없게 느껴진다.
도커 명령어
docker run hello-wolrd
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(arm64v8)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
C++
복사
도커 클라이언트(cli)가 도커 daemon에 contact(도커엔진의 도커서버가 daemon이다.) ⇒ 도커 데몬이 docker hub로부터 “hello-world”이미지를 pull 받음. ⇒ 도커 데몬이 이미지로부터 새로운 컨테이너를 만들어서 실행함 ⇒ 도커 데몬이 output을 docker client로 stream하고 터미널에 보여짐.
Install Ubuntu
docker image ls
docker container ls
docker pull ubuntu
docker container run -it -d --rm --name ubuntuos ubuntu:latest
docker exec -it ubuntuos /bin/bash
{ do someting in Ubuntu, and exit bash }
docker container ls
docker image ls
docker container stop ubuntuos
docker image rm -f ubuntu:latest
docker container ls
docker image ls
C++
복사
우분투 컨테이너가 29MB밖에 되지 않는다. 실제 운영체제가 아니기 때문이다.
컨테이너를 실행하고 bash shell실행했으니 사용자로부터 입력을받기위해 대기한다.
대기를 끝내면 컨테이너는 죽는다. exit해도 죽는다.
bash shell을 실행하지 않고 작업이 종료되면 사용자와 인터렉션이 없으니 죽는다.
컨테이너에서 서버를 띄우는 경우 끝나지 않도록 설정하지 않으면 실행과 동시에 종료된다.
알파인은 오리지널 리눅스 커널이다. 2~3MB밖에 되지 않는다.
우분투는 bash를 쉘로 사용하는데 알파인은 ash를 사용한다.
docker image ls
docker container ls
docker pull alpine
docker container run -it -d --rm --name alpineos alpine:latest
docker exec -it alpineos /bin/ash
{ do someting in Alpine Linux, and exit bash }
docker container ls
docker image ls
docker container stop alpineos
docker image rm -f alpine:latest
docker container ls
docker image ls
Bash
복사
•
-it: 두 가지 옵션의 결합
•
i: 컨테이너의 표준 입력(STDIN)을 활성화합니다. 이를 통해 컨테이너와 상호작용할 수 있습니다.
•
t: 가상 터미널을 할당합니다. 이를 통해 터미널 환경에서 명령어를 실행할 수 있게 됩니다.
•
-d: 이 옵션은 "detached" 모드로 컨테이너를 실행합니다. 즉, 컨테이너가 백그라운드에서 실행되며, 터미널이 해당 컨테이너의 출력을 차지하지 않습니다.
•
—rm: 컨테이너가 중지되면 자동으로 삭제됩니다. 이 옵션을 사용하면 불필요한 컨테이너가 쌓이는 것을 방지할 수 있습니다.
•
—name ubuntuos: 생성할 컨테이너의 이름을 ubuntuos로 지정합니다. 이름을 지정하면 나중에 컨테이너를 쉽게 관리할 수 있습니다.
단일 하이픈은 짧은 옵션을 나타내고 더블 하이픈은 긴 이름의 옵션을 나타낸다.
Dockerfile
FROM
•
이미지 생성 시 기반이 되는 이미지 레이어를 명시
•
<이미지이름>:<태그> 형식으로 작성
•
태그를 붙이지 않으면 자동으로 가장 최신 버전으로 내려받음
(예: ubuntu:14.04)
WORKDIR
•
도커파일 뒤에 오는 모든 지시자(RUN, CMD, COPY, ADD 등)에 대한 작업 디렉토리를 설정
•
리눅스 명령어의 cd와 비슷한 역할
•
작업 디렉토리를 별도로 지정하여, 로컬에 있는 파일을 도커 컨테이너로 복사할 때 분리하는데 쓰임
COPY
•
현재 로컬 컴퓨터에 있는 파일을 도커 컨테이너 안으로 복사하는 기능
RUN
•
도커 이미지가 생성되기 전에 수행할 셀 명령어
CMD
•
컨테이너가 시작됐을 때 실행할 실행 파일 또는 쉘 스크립트
•
이 명령어는 도커 파일 내에서 한 번만 쓸 수 있음
docker의 workdir은 컨테이너가 작업을 수행하기위한 디렉토리. copy로 로컬 컴퓨터에 있는 파일을 도커 컨테이너로 복사해서 사용하는것이다.
Docker Engine
도커엔진 클라이언트는 docker desktop과 docker cli가 있다.
docker cli는 docker로 실행하는 build,pull 등의 명령어를 제공하는 인터페이스이다
docker desktop은 cli를 GUI형태로 구현한것이다.
허브에서 이미지를 다운받고 실행 등의 작업은 백그라운드에서 돌아가는 도커데몬이 한다.
이미지, 컨테이너, 네트워크, 볼륨 등을 만들고 연결하는 역할을 한다.
도커 클라이언트와 도커 서버는 http REST API기반으로 정보를 주고받는다
내 클라이언트로 다른 컴퓨터의 데몬을 통제하는것도 전혀 문제가 없다
이 구조를 합쳐서 도커 엔진이라고 부른다.
Docker Ecosystem
github에 source code, 도커파일 업로드하고 dockerhub에 이미지를 올린다.
개발팀이 만든 컨테이너가 테스트된 후에 production팀이프로그램을 가져다가 실행해야한다.
실행할 컨테이너가 많은 경우 orchestrator를 사용해서 모니터링 하고 죽으면 대수를 맞춰서 컨테이너를 늘리고 줄인다.
개발팀이 소스코드 만들고 컴파일 빌드 마치고 개발서버 올리고 실행파일을 생성해서 올리는 행위가 integration이다. integration은 필요한 프로그램과 자원을 통합하는 과정으로 이미지를 서버에 업로드하는것으로 사람의 역할이 끝난다. integration과정은 자동화되어 continuous하게 진행된다
소스코드와 이미지가 자동으로 테스트되어 실행파일이 만들어진다.
상용서비스를 통해서 고객에게 전달하는 일이 deployment이다.
개발하고 github에서 소스코드를 pull하고 컴파일 및 빌드하고 테스트 모듈을 돌리는 과정을 자동화하는것 CI/CD이고 이를 통해 개발과 operation(운영)이 통합되어 흐르게 하는것이 DevOps이다
Dockerfile layers
FROM, RUN 등 도커 파일의 명령 하나를 layer라고 한다.
최대 레이어 개수는 현재 125개로 제한되어있기 때문에 다섯 개의 레이어를 &&로 한줄로 만들었다.
•
FROM은 베이스 이미지라고 하고 그 위에 내 프로그램을 올린다.
FROM은 docker 이미지의 시작점을 정의한다.
FROM:ubunut:20.24처럼 베이스 이미지를 지정하고 버전을 선택한다.
latest로 하면 가장 최근의 버전을 사용한다.
•
MAINTAINER는 이미지의 유지보수자의 정보를 정의한다.
필수가 아니며 이제는 잘 사용되지 않는다.
•
COPY는 호스트 파일 시스템에서 컨테이너의 파일 시스템으로 디렉토리를 복사한다.
COPY ./app /app처럼 copy src dest형태이며 관례적으로 dest는 /app으로 많이 설정함.
•
WORKDIR는 작업 디렉토리를 지정하며 해당 디렉토리에서 명령어들이 수행된다.
•
EXPOSE는 컨테이너의 공개 포트번호를 지정한다.
이 명령 자체가 포트를 실행해서 리스닝시키는 것이 아니기 때문에 컨테이너를 시작할때 -p옵션을 줘야한다.
•
CMD는 컨테이너 실행시 default로 실행되는 명령이나 파라미터를 설정한다.
ENTRYPOINT와 함께 사용되며 cmd는 ENTRYPOINT에 전달할 인자를 설정한다.
ENTRYPOINT가 설정되지 않았으면 cmd가 단독으로 실행된다.
•
ENTRYPOINT는 컨테이너가 시작될 때 실행할 기본 명령을 설정하고 컨테이너의 기본 동작을 정의한다
위는 우분투 위에서 필요한 것만 지정하는 방식이고 단순하게 파이썬 이미지 사용해도 된다.
layer 0 from scratch
layer 3 from alpine linux는 운영체제 레벨부터 시작
우분투,알파인 등의 이미지는 누군가 layer3까지 만들어놓은것
layer3나 layer6부터 시작하는게 일반적이다.
Lifecyle of Container
리눅스 유닉스의 프로세스 state와 유사하다
pause는 운영체제에서 실행되는 상태에서 멈춘다
pause해도 메모리 상태는 유지되며 CPU를 사용하지 않는다.
컨테이너 실행중에 멈춘다음에 그대로 이미지로 줄수가 있다.
멈춘상태로 이미지로 구워서 디버깅에 쓸수있다. 에러 나기 전의 상태로 배포해서 함께 디버깅.
stop은 컨테이너를 SIGTERM신호를 보내서 정상적으로 종료한다, 데이터 손실 없이 종료된다
kill은 SIGKILL신호를 보내서 프로세스를 강제종료한다.
docker system prune
버그로 인해서 rm -f로 안지워지는 경우 prune을 사용한다. 이제는 거의 사용할 일이 없어졌다.