01-01_FCND]
01-02_JOC]
01-03_Why is Docker?] : 일반적인 software 사용을 위한 설치과정에서 격는 어려움이 존재한다
-
일반적으로 software를 설치하기 위해서는 아래와 같은 절차가 필요하다
-
그리고 설치과정에는 에러를 마주할 가능성이 있고, 이를 해결하기 위해서는 상당히 시간과 비용이 필요할 수 있다
-
도커는 이러한 문제에 대한 해결책을 제시한다
01-04_What is Docker?] : Docker를 왜 사용하지를 알았고, 그럼 Docker는 뭐하는 놈인가?
-
Docker는 Docker 생태계를 말하며, Docker를 사용한다는 것은 생태계가 제공하는 여러 utilities를 사용하고 있다는 것을 말한다
-
Docker를 통해, 최종적으로 생성된 container는 Image로부터 생성된 하나의 프로그램이다
01-05_Dcoker for Mac/Windows]
-
Docker를 사용하기 위해서, Docker Client가 필요하고 각 PC 운영체제에 맞게 설치해야 한다
-
Docker Client(Docker CLI)는 원하는 Docker 명령을 실행시키도록 도와주는 Tools이다
**01-06_Installing **Docker on macOS]
**01-07_Installing **Docker with WSL on Windows 10/11]
**01-08_Installing **Docker on Linux]
01-09_Using the Docker Client**]**
- docker client를 설치했다면, docker 명령어를 docker server로 전달할 수 있다
- docker version : version명령으로 server 정보를 확인할 수 있다, Server는 linux/arm64를 사용하고 있다걸 확인할 수 있다
➜ ~ docker version Client: Cloud integration: v1.0.35+desktop.10 Version: 25.0.2 API version: 1.44 Go version: go1.21.6 Git commit: 29cf629 Built: Thu Feb 1 00:18:45 2024 OS/Arch: darwin/arm64 Context: desktop-linux
Server: Docker Desktop 4.27.1 (136059) Engine: Version: 25.0.2 API version: 1.44 (minimum version 1.24) Go version: go1.21.6 Git commit: fce6e0c Built: Thu Feb 1 00:23:21 2024 OS/Arch: linux/arm64 Experimental: false containerd: Version: 1.6.28 GitCommit: ae07eda36dd25f8a1b98dfbf587313b99c0190bb runc: Version: 1.1.12 GitCommit: v1.1.12-0-g51d5e94 docker-init: Version: 0.19.0 GitCommit: de40ad0 ➜ ~
-
$ docker run hello-world 명령시 어떠한 일이 일어날까? >> Docker Server가 Image Cache에 저장된 image 존재유무를 확인하고, 없다면 Docker Hub에서 가져온다
01-10_But Really...What's a Container**]**
-
container의 동작 원리를 알기 위해서, Operating System에 대해 어느 정도 이해가 필요하다
-
대부분의 OS는 Kernel을 가지고 있는데, kernel은 모든 programs이 HW 컴퓨터 자원(CPU, Memory, Hard Dist etc...)에 대한 사용 권한을 매니징하는 역할을 수행한다
-
예를 들어, NodeJS program이 Hard Disk에 특정 내용을 저장하고 싶다는 System Call을 통해 Kernel에 Hard Disk로 접근 요청을 해야 한다
-
다른 예로, Python v2를 사용하는 Chrome과 Python v3를 사용하는 NodeJS가 있는데, Hard Disk에 접근은 v2만 가능한 상황이다
-
어떻게 이 문제를 해결해야 하나?
-
HW(Hard Disk)를 namespacing을 사용해야 하는데, Segment를 분리해서 연결시켜야 한다
-
이를 통해 Chrome은 V2에 접근하게 하고, NodeJS는 V3에 접근하게 한다
-
결국, 하나의 장비에서 Chrome과 NodeJS가 운영될 수 있다
-
Namespacing이란 process(program)당 Isolated된 HW를 할당받아 사용하게 만드는 걸 말한다
-
Control Groups(cgroups)이란 process(program)당 자원의 사용이 제한되어 동시에 사용이 불가한 자원으로 포트가 이에 해당한다
-
그리하여, 아래 점선으로 표기된 부분은 Chrome이 Isolated된 영역을 이용하는 모습을 보여준다
-
좀 더 구체화한 모습은 아래와 같다
-
실제적으로, Chome을 실행하는 Container가 있다고 했을 때
-
아래 그림과 같이, [FS Snapshot]이 Hard Disk로 Copy되고 Chrome 프로그램이 실행된다.
**01-11_How's **Docker Running on Your Computer]
-
docker client를 설치했고, container를 실행시켰다는 것은 Linux Virtual Machine에서 process(container)가 run한다는 의미다
02-12_Docker Run in Detail**]**
-
Docker Container를 실행하기
-
$ docker run <image name>
-
Image에 정의된 "hello-world"라는 binary가 Linux-Virtual-Machine에 있는 hard disk 저장되고, binary가 실행된다
-
여기서, Default Command가 실행된 것이다
-
Container에 process가 looping하지 않은 process는 exit(종료)되고, looping하는 process는 up(running)상태로 남는다
02-13_Overriding Default Commands**]**
- 기본 명령어를 지정하는 방법이 있다
- $ docker run <image name> <command>
- Startup Command가 <command>로 지정된다
02-14_Listing Running Containers**]**
-
container(process) 리스트를 보여준다
-
$ docker ps : status가 up으로 running 상태의 container를 보여준다
-
$ docker ps -a : 모든 상태의 container를 보여준다
02-15_Container Lifecycle**]**
- container(process) 리스트를 봤는데, 왜 shutdown(exit)되는가?
- 먼저, docker run 은 docker create(container 생성) + docker start(container 실행)을 의미한다
- container가 생성되고 startup command로 process가 끝나면 container(process)가 shutdown된다
- $ docker start -a <container id> : -a는 Attach STDOUT/STDERR and forward signals
➜ ~ docker create hello-world d617efa3c329824b2a171472b71bcf1eefca05a76201c770d0280aa3a8460105 ➜ ~ docker start -a d617efa3c329824b2a171472b71bcf1eefca05a76201c770d0280aa3a8460105
Hello from Docker! This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
- The Docker client contacted the Docker daemon.
- The Docker daemon pulled the "hello-world" image from the Docker Hub. (arm64v8)
- The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading.
- The Docker daemon streamed that output to the Docker client, which sent it to your terminal.
To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID: https://hub.docker.com/
For more examples and ideas, visit: https://docs.docker.com/get-started/
➜ ~
02-16_Restarting Stopped Container**]**
- $ docker run busybox echo hi there 로 container를 생성했다
- 해당 container는 exited 상태이고, 다시 실행을 위해 $ docker start <container id> 명령으로 재실행이 가능하다
- $ docker start -a <container id>로 STDOUT을 볼 수 있다
- $ docker start -a <container id> echo bye there은 start 사용법상 여러 <container id>가 나열되어야 한다
➜ ~ docker run busybox echo hi there Unable to find image 'busybox:latest' locally latest: Pulling from library/busybox 835f85a6d665: Pull complete Digest: sha256:c230832bd3b0be59a6c47ed64294f9ce71e91b327957920b6929a0caa8353140 Status: Downloaded newer image for busybox:latest hi there ➜ ~ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a8da300f416a busybox "echo hi there" 5 seconds ago Exited (0) 4 seconds ago focused_varahamihira ➜ ~ docker start a8da300f416a a8da300f416a ➜ ~ docker start -a a8da300f416a hi there ➜ ~ docker start -a a8da300f416a echo bye there you cannot start and attach multiple containers at once ➜ ~ docker start --help
Usage: docker start [OPTIONS] CONTAINER [CONTAINER...]
Start one or more stopped containers
Aliases: docker container start, docker start
Options: -a, --attach Attach STDOUT/STDERR and forward signals --detach-keys string Override the key sequence for detaching a container -i, --interactive Attach container's STDIN ➜ ~
02-17_Removing Stopped Container**]**
- $ docker system prune : 불필요한 container, image, cache, network 등을 삭제한다
- docker 작업을 마치고, 추가 작업이 없는 경우 자원을 낭비하지 않도록 해당 명령을 수행하자
➜ ~ docker system prune WARNING! This will remove: - all stopped containers - all networks not used by at least one container - all dangling images - unused build cache
Are you sure you want to continue? [y/N] y Deleted Containers: 5ec79aa7b10d6e4660bafe74a9a97b8412c18d45f24dc5b0fd2d287ce70abed3 a8da300f416ac1a930c00177c37ac360c78cde9bb67f8692dda9ec78d654975b
Total reclaimed space: 0B ➜ ~
02-18_Retrieving Log Output**]**
-
$ docker logs <container id> : Fetch the logs of a container
➜ ~ docker create busybox echo hi there 932b3a005c553eeb6c941cd31850c76c80f7888222f114feb37a771d1c8d9fca ➜ ~ docker start 932b3a005c553eeb6c941cd31850c76c80f7888222f114feb37a771d1c8d9fca 932b3a005c553eeb6c941cd31850c76c80f7888222f114feb37a771d1c8d9fca ➜ ~ docker logs 932b3a005c553eeb6c941cd31850c76c80f7888222f114feb37a771d1c8d9fca hi there ➜ ~ docker start 932b3a005c553eeb6c941cd31850c76c80f7888222f114feb37a771d1c8d9fca 932b3a005c553eeb6c941cd31850c76c80f7888222f114feb37a771d1c8d9fca ➜ ~ docker logs 932b3a005c553eeb6c941cd31850c76c80f7888222f114feb37a771d1c8d9fca hi there hi there ➜ ~
02-19_Stopping Containers**]**
-
계속 Status: UP(running) 중인 container를 중지시키는 방법
02-20_Multi-Command Containers**]**
-
redis-server가 돌고 있는 container에 외부에서 redis-cli를 실행해도 바로 container 내 redis-server와 연결할 수 없다
02-21_Executing Commands in Running Containers**]**
-
그렇다면, redis-server가 Status:UP(running)인 container에 명령을 실행시킬 수 있다
-
$ docker exec -it <container id> <command>
➜ ~ docker run redis Unable to find image 'redis:latest' locally latest: Pulling from library/redis 92c3b3500be6: Pull complete 631720f833ee: Pull complete 704a08909867: Pull complete 090311ee98f0: Pull complete 50eb2e3e87d6: Pull complete 4a05d8378bf0: Pull complete 4f4fb700ef54: Pull complete 713e6192e133: Pull complete Digest: sha256:eadf354977d428e347d93046bb1a5569d701e8deb68f090215534a99dbcb23b9 Status: Downloaded newer image for redis:latest 1:C 18 Sep 2024 11:22:16.175 * oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 1:C 18 Sep 2024 11:22:16.175 * Redis version=7.4.0, bits=64, commit=00000000, modified=0, pid=1, just started 1:C 18 Sep 2024 11:22:16.175 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf 1:M 18 Sep 2024 11:22:16.175 * monotonic clock: POSIX clock_gettime 1:M 18 Sep 2024 11:22:16.176 * Running mode=standalone, port=6379. 1:M 18 Sep 2024 11:22:16.176 * Server initialized 1:M 18 Sep 2024 11:22:16.176 * Ready to accept connections tcp
^Z [1] + 13309 suspended docker run redis ➜ ~ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 882dfc420465 redis "docker-entrypoint.s…" 26 seconds ago Up 24 seconds 6379/tcp thirsty_elgamal ➜ ~ docker exec -it 882dfc420465 redis-cli 127.0.0.1:6379> set myvalue 5 OK 127.0.0.1:6379> get myvalue "5" 127.0.0.1:6379>
02-22_The Purpose of the IT Flag**]**
-
$ docker exec -it에서 이 flag들의 의미는?
-
-i : terminal을 통해 process와 STDIN를 전달하고, STDOUT STDERR를 받는다
-
-t : Allocate a pseudo-TTY (보기 좋게 표시해준다)
02-23_Getting a Command Prompt in a Container**]**
-
매번 container에 exec로 명령을 수행할 필요없이, shell command로 container에 접근해 명령을 수행할 있다
➜ ~ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 882dfc420465 redis "docker-entrypoint.s…" 11 minutes ago Up 10 minutes 6379/tcp thirsty_elgamal 932b3a005c55 busybox "echo hi there" 41 minutes ago Exited (0) 41 minutes ago sad_rubin ➜ ~ docker exec -it 882dfc420465 bash root@882dfc420465:/data# redis-cli 127.0.0.1:6379> get myvalue "5" 127.0.0.1:6379>
02-24_Starting with a Shell**]**
- container를 실행할때, shell이 FS snapshot에 있는 경우 바로 실행시킬 수 있다
- $ docker run -it busybox sh
➜ ~ docker run -it busybox sh / # ls bin dev etc home lib lib64 proc root sys tmp usr var / #
02-25_Container Isolation**]**
- 생성된 container는 Isolated 상태로 서로 영향을 주지 않는 독립 공간이다
➜ ~ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3ec31ad00755 busybox "sh" 13 seconds ago Up 13 seconds hardcore_gould 1632d24b635e busybox "sh" 7 minutes ago Up 7 minutes sweet_dewdney ➜ ~
[CONTAINER ID : 3ec31ad00755] / # ps -ef PID USER TIME COMMAND 1 root 0:00 sh 10 root 0:00 ps -ef / # ifconfig eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:03 inet addr:172.17.0.3 Bcast:172.17.255.255 Mask:255.255.0.0 UP BROADCAST RUNNING MULTICAST MTU:65535 Metric:1 RX packets:13 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:1006 (1006.0 B) TX bytes:0 (0.0 B)
lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
/ # ls bin dev etc home lib lib64 proc root sys tmp usr var / # touch con3ec31ad00755 / # ls bin dev home lib64 root tmp var con3ec31ad00755 etc lib proc sys usr / #
[CONTAINER ID : 1632d24b635e] / # ps -ef PID USER TIME COMMAND 1 root 0:00 sh 8 root 0:00 ps -ef / # ifconfig eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:04 inet addr:172.17.0.4 Bcast:172.17.255.255 Mask:255.255.0.0 UP BROADCAST RUNNING MULTICAST MTU:65535 Metric:1 RX packets:10 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:796 (796.0 B) TX bytes:0 (0.0 B)
lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
/ # ls bin dev etc home lib lib64 proc root sys tmp usr var / # touch con1632d24b635e / # ls bin dev home lib64 root tmp var con1632d24b635e etc lib proc sys usr / #
03-26_Creating Docker Images**]**
-
지금까지 다른 engineer가 만든 이미지를 사용했고, 우리가 원하는 이미지를 만들기 위해서는 Dockerfile을 만들어야 한다
-
Dockerfile을 build하면 Docker Client가 Docker Server로 Dockerfile에 맞는 Image를 생성한다
-
Dockerfile은 보통 다음과 같은 Flow로 작성한다
03-27_BfDD**]**
03-28_Building a Dockerfile**]**
- redis-server 를 만들어 보겠다
Specify a base image : Use an existing docker image as a base
FROM alpine
Run some commands to install additional programs : Download and install a dependency
RUN apk add --update redis
Specify a command to run on container startup : Tell the image what to do when it starts as a container
CMD ["redis-server"]
- Dockerfile로 이미지 만들기
➜ redis-image sudo docker build . [+] Building 6.3s (7/7) FINISHED docker:desktop-linux => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 358B 0.0s => [internal] load metadata for docker.io/library/alpine:latest 3.5s => [auth] library/alpine:pull token for registry-1.docker.io 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [1/2] FROM docker.io/library/alpine:latest@sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d 0.0s => => resolve docker.io/library/alpine:latest@sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d 0.0s => => sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d 1.85kB / 1.85kB 0.0s => => sha256:9cee2b382fe2412cd77d5d437d15a93da8de373813621f2e4d406e3df0cf0e7c 528B / 528B 0.0s => => sha256:c157a85ed455142fd79bff5dce951fd5f5b0d0c6e45e6f54cfd0c4e2bdec587b 1.49kB / 1.49kB 0.0s => [2/2] RUN apk add --update redis 2.7s => exporting to image 0.0s => => exporting layers 0.0s => => writing image sha256:f396f6ca44e6b28c049339480b6c532de62948335996eab74a715b3099f3d9f9 0.0s View build details: docker-desktop://dashboard/build/desktop-linux/desktop-linux/swr131jc1gwyhtycv5bybvv6d
Whats Next? View a summary of image vulnerabilities and recommendations → docker scout quickview ➜ redis-image docker images REPOSITORY TAG IMAGE ID CREATED SIZE <none> <none> f396f6ca44e6 11 seconds ago 15.5MB ➜ redis-image docker run f396f6ca44e6 1:C 18 Sep 2024 15:05:01.471 * oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 1:C 18 Sep 2024 15:05:01.471 * Redis version=7.2.5, bits=64, commit=00000000, modified=0, pid=1, just started 1:C 18 Sep 2024 15:05:01.471 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf 1:M 18 Sep 2024 15:05:01.471 * monotonic clock: POSIX clock_gettime 1:M 18 Sep 2024 15:05:01.472 * Running mode=standalone, port=6379. 1:M 18 Sep 2024 15:05:01.472 * Server initialized 1:M 18 Sep 2024 15:05:01.472 * Ready to accept connections tcp
➜ .docker docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0f3709b6c900 f396f6ca44e6 "redis-server" 23 seconds ago Up 22 seconds zealous_allen ➜ .docker
03-29_Dockerfile Teardown**]**
-
Dockerfile을 분석해보자
03-30_What's a Base Image?****]
-
dockerfile에서 base image는 software를 설치(구축) 및 실행하기 위한 환경이다
03-31_The Build Process in Detail**]**
-
Dockerfile의 명령어 실행마다 이미지가 생성되고, 생성된 이미지에 다음 단계의 명령이 실행되어 새로운 이미지가 만들어진다
03-32_A Brief Recap**]**
03-33_Rebuilds with Cache**]**
-
Dockerfile의 명령어 실행마다 이미지가 생성되고, 생성된 이미지 캐시에 저장되어 빌드시 여러번 이미지 생성하지 않고 재사용한다
03-34_Tagging an Image**]**
-
custom 이미지에 tag를 달아 image 이름을 지정할 수 있다
-
Docker ID를 앞에 붙여, custom image 이름을 지정할 수 있고, Docker ID가 없다면 공식 public 이미지로 간주된다
03-35_Quick Note for Windows Users**]**
03-36_Manual Image Generation with Docker Commit**]**
-
container로 image를 만들수 있다
-
container를 실행하고, container 내부에서 추가작업(RUN, 설치)를 한 후 image로 만들 수 있다
-
docker commit -c 'CMD ["~~~"]' <container id>
-
새로운 이미지가 생성된다
04-37_Project Outline**]**
-
이번엔 NodeJS web app을 만들어 보자
-
중간에 발생할 수 있는 오류를 수정하는 과정도 알아본다
04-38_Node Server Setup**]**
- NodeJS Express 서버 세팅을 한다 (동일한 파일 경로에 아래 두 파일이 위치한다)
- package.json
{ "dependencies": { "express": "*" }, "scripts": { "start": "node index.js" } }
- index.js
const express = require('express');
const app = express();
app.get('/', (req, res) => { res.send('Hi there'); });
app.listen(8080, () => { console.log('Listening on port 8080'); })
04-39_Reminder on Buildkit**]**
As mentioned earlier, Buildkit will hide away much of its progress which is something the legacy builder did not do. In the upcoming lectures will be discussing some output that will be quickly hidden by default. To see this output, you will want to pass the progress flag to the build command:
docker build --progress=plain .
Additionally, you can pass the no-cache flag to disable any caching:
docker build --no-cache --progress=plain .
Note - Do not try to use the no-cache flag with Lecture 47 Minimizing Cache Busting
Disabling Buildkit to match course output
To disable Buildkit, you can just pass the following variable to the build command:
DOCKER_BUILDKIT=0 docker build .