Kubernetes in Action, Second Edition MEAP V15 정리중
Container는 VM과 다르게 하나의 OS 위에서 process 단위로만 나눈다
-> VM보다 훨씬 가벼움
하나의 Container위에서는 무조건 하나의 application만 동작!

system call등을 단일 kernel 하나로만 처리함. 하지만 container들끼리는 다른 container를 무시하고 자신만 kernel과 통신하는 것으로 취급됨. 하지만 논리적으로 완벽한 분리는 아니므로 VM보다 안정적으로 독립성 보장은 X.

application을 패키징하여 distributing, running하는 플랫폼으로 도커를 사용하면 application을 필요한 환경(DLL, OS의 부분 등)과 하나로 묶어 다른 OS를 가진 어떤 컴퓨터 위에서든 실행 가능
Docker의 핵심 개념 3가지
Image - application과 필요한 환경을 하나로 묶어 zip해 놓은 패키지 단위
Registry - Image의 저장소이고, 다른사람과 공유 가능. git같은 개념인듯
Container - Image를 instance화 하여 제한된 리소스 하에서 실행하는 공간
Image layer
application을 실행하기 위한 요구사항들을 layer로 쌓아서 관리함
Q. 그러면 container 공통으로 쓰이는 file들에 대해서는 자원의 변경사항을 공유하는 것 아닌가?
A. container 각각의 read-write layer에서 file을 수정하므로 read-only layer에 있는 원본에는 변화 X

Docker에서는 자체적인 kernel를 가지고 있지 않으므로 application이 요구하는 kernel 버전이나 kernel module이 없으면 실행 불가능
-> hardware architecture이 다르면(ex. x86과 ARM) 실행 불가능

Docker자체는 process를 격리하지 않고, 실제 container 격리는 linux kernel 수준에서 이루어진다.
busybox - echo, ls등 linux 명령어들 모아놓은 단일파일
$ docker run busybox echo "Hello World"
실행하면 다음과 같이 나온다.
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
7c9d20b9b6cd: Pull complete
Digest: sha256:fe301db49df08c384001ed752dff6d52b4…
Status: Downloaded newer image for busybox:latest
Hello World
이것의 작동 원리는 다음과 같다.

1. Docker CLI에서 Docker daemon에 명령 전달
2. Docker daemon이 로컬에서 해당 image 있는지 확인
3. 없으므로 registry에서 image 가져옴
4. Docker에서 container 만든 후 echo "Hello World" 커맨드 실행
// app.js
const http = require('http');
const os = require('os');
const listenPort = 8080;
36
©Manning Publications Co. To comment go to liveBook
console.log("Kubia server starting...");
console.log("Local hostname is " + os.hostname());
console.log("Listening on port " + listenPort);
var handler = function(request, response) {
let clientIP = request.connection.remoteAddress;
console.log("Received request for "+request.url+" from "+clientIP);
response.writeHead(200);
response.write("Hey there, this is "+os.hostname()+". ");
response.write("Your IP is "+clientIP+". ");
response.end("\n");
};
var server = http.createServer(handler);
server.listen(listenPort);
// Dockerfile
FROM node:12
ADD app.js /app.js
ENTRYPOINT ["node", "app.js"]
Docker cli로 실행시켜준다.
$ docker build -t kubia:latest .
완성된 image는 docker images 명령어로 확인해보면 다음과 같이 나온다.
kubia latest ca0deb942e03 About a minute ago 918MB
빌드의 원리는 다음과 같다.

이미지를 실행하려면 다음 명령어를 입력한다.
$ docker run --name kubia-container -p 1234:8080 -d kubia
kubia 이미지로부터 kubia-container라는 이름의 컨테이너를 만들고 local 컴퓨터의 1234포트를 컨테이너의 8080과 연결하여 실행한다.

이미지에 tag(이미지의 다른 이름 + 버전정보)를 붙여준다.
$ docker tag kubia luksa/kubia:1.0
docker에 로그인한 후 업로드한다.
$ docker login -u yourid -p yourpassword docker.io
$ docker push yourid/kubia:1.0
다른 컴퓨터에서 이미지를 받아 쓰려면 다음을 입력한다.
$ docker run -p 1234:8080 -d yourid/kubia:1.0
컨테이너를 종료시킨다.
$ docker stop kubia-container
컨테이너와 이미지를 삭제한다.
$ docker rmi kubia:latest
OS의 자원들을 분할해주는 단위, process는 각각의 자원별로(파일, 네트워크, 시스템 이름 등) 자기만의 namespace를 설정하여 그 안의 자원만 참조한다.
but) 가끔씩 프로세스가 같은 namespace를 공유하게 하고 싶을 수도 있다.
어떤 network interface들을 사용할 것인지 정의해 놓는 namespace. 하나의 network interface는 하나의 network namespace에만 소속될 수 있다.

프로세스가 system host name과 domain name을 뭐라고 보는지 정의하는 namespace.
두 프로세스의 UTS namespace가 다르면 서로 다른 컴퓨터 환경에서 돌아가는 것이라고 여기게 된다.
Linux namespace에서는 같은 OS 자원을 얼마만큼 사용할지는 정의 X
Linux Control Groups를 통해 사용하는 cpu, memory 등의 할당량 설정 가능.
프로세스가 어떤 system call 실행 등의 시스템 자원을 건드릴 수 있는지 권한을 설정함으로써 커널 내부의 데이터들이 이상하게 바뀌는 것 방지