Docker는 개발자들 사이에서 가장 많이 이용되고 있는 컨테이너 기술로서, 다양한 애플리케이션을 효율적으로 구동시키고 관리하는 데 있어 필수적인 프로그램이다. Docker의 기본 개념과 설치 및 기본 환경 구성 방법을 정리하였다.
[목차]
2. 컨테이너 vs 가상머신 (Virtual Machine)
1. Docker에 대한 설명
Docker는 컨테이너라는 개념을 기반으로 한 오픈 소스 플랫폼이다. 컨테이너는 애플리케이션을 실행하는 환경을 격리시키는 역할을 한다. 이를 통해 소프트웨어를 표준화된 단위로 패키징하고 배포할 수 있게 하여 서버의 자원 관리와 프로젝트를 효율적으로 처리할 수 있게 되었다. Docker의 기본 구조는 Docker Engine, Docker Image, 그리고 Docker Container로 이루어져 있다. Docker Engine은 Docker 이미지를 실행하는 데 필요한 실질적인 도구를 제공하고, Docker Image는 애플리케이션과 필요한 라이브러리, 도구들을 패키징 한 것이며, Docker Container는 이 이미지를 기반으로 실행된 실제 인스턴스를 의미한다. Docker는 표준화된 단위로 애플리케이션을 패키징 하므로, 다양한 환경에서 동일하게 실행될 수 있다는 장점이 있다. 또한, 컨테이너 기반의 가벼운 가상화를 제공하기 때문에, 빠른 동작 속도와 높은 성능을 유지할 수 있다. 이러한 특징들은 소프트웨어 개발, 테스트, 배포 등의 프로세스를 개선하고, DevOps와 소프트웨어 아키텍처 등의 개발 편의 성에 초점이 맞춰져 있다고 할 수 있다.
2. 컨테이너 vs 가상머신 (Virtual Machine)
컨테이너와 가상머신은 동작 결과로 보았을 때 큰 차이는 없고 동일한 목표를 가진 프로그램으로 볼 수 있다. 하지만 동작하는 방법에 특징 적인 차이점이 있는데 이점을 비교해 보았다. 이 차이점을 확인해 보면 docker를 사용하는 데 있어서 기본적인 개념을 이해하는데 도움이 된다.
항목 | 컨테이너 | 가상머신 (Virtual Machine) |
구조 및 작동 방식 | 호스트 시스템의 커널을 공유하면서 프로세스를 격리 |
전체 운영 체제를 에뮬레이션 |
자원 효율 | 호스트 시스템의 리소스를 공유하여 가볍고 빠름 | 운영 체제와 함께 필요한 자원을 할당받아 사용 |
이미지 관리 | 레이어 기반의 이미지 시스템을 사용, 효율적인 관리 가능 |
일반적으로 큰 이미지 파일을 관리, 저장 공간을 많이 차지하고 관리가 복잡함. |
이식성 | 어디에서나 동일하게 실행될 수 있도록 설계 |
하드웨어 에뮬레이션 레벨에서 운영됨, 하드웨어와 호환성 문제가 발생할 수 있음 |
보안 | 호스트 시스템의 커널을 공유, 커널 레벨에서의 취약점이 컨테이너에 영향을 줄 수 있음 | 각각 독립된 운영 체제를 가지므로 다른 VM에 영향을 미치지 않음 |
구동 시간 | Docker 컨테이너의 시작 시간은 보통 초 단위 | 컨테이너에 비해 비교적 느림 |
저장 공간 | 이미지 레이어를 공유함, 저장 공간을 최소화 | 각 VM은 전체 운영 체제와 애플리케이션을 포함한 별도의 이미지 필요로함 용량 큼 |
스케일링 및 배포 | 빠르고 쉬운 스케일링, 이미지 기반 배포 가능 | 스케일링과 배포는 일반적으로 더 복잡하고 시간이 걸림 |
3. Docker 설치 방법
- 설치 환경
# cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=22.04
DISTRIB_CODENAME=jammy
DISTRIB_DESCRIPTION="Ubuntu 22.04.2 LTS"
# uname -r
5.15.0-72-generic
- 설치에 필요한 의존성 프로그램 설치
# apt-get update
# apt-get install apt-transport-https ca-certificates curl software-properties-common
- Docker 공식 GPG 키 추가
# curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/docker.gpg
- Docker 저장소 설정 (Docker 저장소를 apt 패키지 관리 도구에 추가함)
# add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
- Docker 패키지 설치
# apt-get update
# apt-get install docker-ce
- docker 서비스 체크
# systemctl status docker
● docker.service - Docker Application Container Engine
Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2023-06-27 10:45:23 KST; 8s ago
TriggeredBy: ● docker.socket
Docs: https://docs.docker.com
Main PID: 4130 (dockerd)
Tasks: 11
Memory: 28.2M
CPU: 240ms
CGroup: /system.slice/docker.service
└─4130 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
Jun 27 10:45:23 gbminnote.com systemd[1]: Starting Docker Application Container Engine...
Jun 27 10:45:23 gbminnote.com dockerd[4130]: time="2023-06-27T10:45:23.221510289+09:00" level=info msg="Starting up"
Jun 27 10:45:23 gbminnote.com dockerd[4130]: time="2023-06-27T10:45:23.290195164+09:00" level=info msg="Loading containers: start."
Jun 27 10:45:23 gbminnote.com dockerd[4130]: time="2023-06-27T10:45:23.548860750+09:00" level=info msg="Loading containers: done."
Jun 27 10:45:23 gbminnote.com dockerd[4130]: time="2023-06-27T10:45:23.564760362+09:00" level=info msg="Docker daemon" commit=659604f graphdriver=overlay2 version=24.0.2
Jun 27 10:45:23 gbminnote.com dockerd[4130]: time="2023-06-27T10:45:23.564849080+09:00" level=info msg="Daemon has completed initialization"
Jun 27 10:45:23 gbminnote.com dockerd[4130]: time="2023-06-27T10:45:23.590229732+09:00" level=info msg="API listen on /run/docker.sock"
Jun 27 10:45:23 gbminnote.com systemd[1]: Started Docker Application Container Engine.
- 버전 체크
# docker version
Client: Docker Engine - Community
Version: 24.0.2
API version: 1.43
Go version: go1.20.4
Git commit: cb74dfc
Built: Thu May 25 21:51:00 2023
OS/Arch: linux/amd64
Context: default
Server: Docker Engine - Community
Engine:
Version: 24.0.2
API version: 1.43 (minimum version 1.12)
Go version: go1.20.4
Git commit: 659604f
Built: Thu May 25 21:51:00 2023
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.6.21
GitCommit: 3dce8eb055cbb6872793272b4f20ed16117344f8
runc:
Version: 1.1.7
GitCommit: v1.1.7-0-g860f061
docker-init:
Version: 0.19.0
GitCommit: de40ad0
4. Docker 명령어 살펴보기
# docker
Usage: docker [OPTIONS] COMMAND
A self-sufficient runtime for containers
Common Commands:
run Create and run a new container from an image
exec Execute a command in a running container
ps List containers
build Build an image from a Dockerfile
pull Download an image from a registry
push Upload an image to a registry
images List images
login Log in to a registry
logout Log out from a registry
search Search Docker Hub for images
version Show the Docker version information
info Display system-wide information
Management Commands:
builder Manage builds
buildx* Docker Buildx (Docker Inc., v0.10.5)
compose* Docker Compose (Docker Inc., v2.18.1)
container Manage containers
context Manage contexts
image Manage images
manifest Manage Docker image manifests and manifest lists
network Manage networks
plugin Manage plugins
system Manage Docker
trust Manage trust on Docker images
volume Manage volumes
Swarm Commands:
swarm Manage Swarm
Commands:
attach Attach local standard input, output, and error streams to a running container
commit Create a new image from a container's changes
cp Copy files/folders between a container and the local filesystem
create Create a new container
diff Inspect changes to files or directories on a container's filesystem
events Get real time events from the server
export Export a container's filesystem as a tar archive
history Show the history of an image
import Import the contents from a tarball to create a filesystem image
inspect Return low-level information on Docker objects
kill Kill one or more running containers
load Load an image from a tar archive or STDIN
logs Fetch the logs of a container
pause Pause all processes within one or more containers
port List port mappings or a specific mapping for the container
rename Rename a container
restart Restart one or more containers
rm Remove one or more containers
rmi Remove one or more images
save Save one or more images to a tar archive (streamed to STDOUT by default)
start Start one or more stopped containers
stats Display a live stream of container(s) resource usage statistics
stop Stop one or more running containers
tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
top Display the running processes of a container
unpause Unpause all processes within one or more containers
update Update configuration of one or more containers
wait Block until one or more containers stop, then print their exit codes
Global Options:
--config string Location of client config files (default "/root/.docker")
-c, --context string Name of the context to use to connect to the daemon (overrides DOCKER_HOST env var and default context set with "docker context use")
-D, --debug Enable debug mode
-H, --host list Daemon socket to connect to
-l, --log-level string Set the logging level ("debug", "info", "warn", "error", "fatal") (default "info")
--tls Use TLS; implied by --tlsverify
--tlscacert string Trust certs signed only by this CA (default "/root/.docker/ca.pem")
--tlscert string Path to TLS certificate file (default "/root/.docker/cert.pem")
--tlskey string Path to TLS key file (default "/root/.docker/key.pem")
--tlsverify Use TLS and verify the remote
-v, --version Print version information and quit
Run 'docker COMMAND --help' for more information on a command.
For more help on how to use Docker, head to https://docs.docker.com/go/guides/
5. Docker 이미지 관리
- 이미지 확인 (기본 이미지가 없음)
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
- 다운로드할 이미지 검색 (Docker Hub에서도 받을 수 있음 하단 내용을 참고)
# docker search ubuntu
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
ubuntu Ubuntu is a Debian-based Linux operating sys… 16104 [OK]
websphere-liberty WebSphere Liberty multi-architecture images … 294 [OK]
open-liberty Open Liberty multi-architecture images based… 61 [OK]
neurodebian NeuroDebian provides neuroscience research s… 100 [OK]
ubuntu-debootstrap DEPRECATED; use "ubuntu" instead 51 [OK]
ubuntu-upstart DEPRECATED, as is Upstart (find other proces… 114 [OK]
ubuntu/nginx Nginx, a high-performance reverse proxy & we… 96
ubuntu/cortex Cortex provides storage for Prometheus. Long… 3
~ 생략
# docker search rocky
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
rockylinux The official build of Rocky Linux. 158 [OK]
rockylinux/rockylinux 57
kasmweb/rockylinux-9-desktop Rocky Linux 9 desktop for Kasm Workspaces 0
kasmweb/rockylinux-8-desktop Rocky Linux 8 desktop for Kasm Workspaces 0
rockylinux/rocky-toolbox Toolbox image for Rocky Linux - https://gith… 1
rockylinux/rockylinux-shim RockyLinux shim-review images 0
dokken/rockylinux-8 A docker container for use with Test Kitchen… 4
dokken/rockylinux-9 2
spack/rockylinux8 0
spack/rockylinux9 0
~ 생략
- 이미지 다운로드
# docker pull ubuntu
Using default tag: latest
latest: Pulling from library/ubuntu
6b851dcae6ca: Pull complete
Digest: sha256:6120be6a2b7ce665d0cbddc3ce6eae60fe94637c6a66985312d1f02f63cc0bcd
Status: Downloaded newer image for ubuntu:latest
docker.io/library/ubuntu:latest
# docker pull rockylinux/rockylinux:9
9: Pulling from rockylinux/rockylinux
4031b0359885: Pull complete
Digest: sha256:984ef1ce766960f62ee3caebf316ff96a5c8190d1095258f670ee5da1afdf47e
Status: Downloaded newer image for rockylinux/rockylinux:9
docker.io/rockylinux/rockylinux:9
- 이미지 확인
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest 99284ca6cea0 3 weeks ago 77.8MB
rockylinux/rockylinux 8 27d7eace79e5 5 weeks ago 197MB
rockylinux/rockylinux 9 175264fac6da 5 weeks ago 176MB
- 이미지 삭제 방법
# docker rmi rockylinux/rockylinux:8
Untagged: rockylinux/rockylinux:8
Untagged: rockylinux/rockylinux@sha256:f197fdea1b7802f3592d2af2d21f802d5b8ac199e80d29c48a1b3fdc7e0026cb
Deleted: sha256:27d7eace79e5054906e3952b322a896efc1bc8025db42b3f3b85fc140ed093cc
Deleted: sha256:964fc91a3863b6ffb1c39ac4ebb910c52f6feaedbd961503b6ddb6fade3f2423
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest 99284ca6cea0 3 weeks ago 77.8MB
rockylinux/rockylinux 9 175264fac6da 5 weeks ago 176MB
6. Docker 컨테이너 관리
- 컨테이너 생성 방법
docker run -d -p 외부포트:컨테이너포트 --name 컨테이너이름 이미지이름:태그
- 생성 예
# docker run -it -d -p 11922:22 --hostname node01.gbminnote.com --name gbmin_node01 ubuntu:latest
90845deed7eb4eab6c0d88e93ec959bfd6c7e8051cb1235cc897f9a0efedd1bd
# docker run -it -d -p 22922:22 --hostname node02.gbminnote.com --name gbmin_node02 ubuntu:latest
65c257fde7668debe8868bc95f19c75588a17015d8327b06512efa95da45ddd2
# docker run -it -d -p 33922:22 --hostname node03.gbminnote.com --name gbmin_node03 ubuntu:latest
8e538b37d1dc784a82f96025370e4b6fdb736cda41efb4aa5e4ee60ebeff038c
- 생성된 컨테이너 확인
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8e538b37d1dc ubuntu:latest "/bin/bash" 18 seconds ago Up 17 seconds 0.0.0.0:33922->22/tcp, :::33922->22/tcp gbmin_node03
65c257fde766 ubuntu:latest "/bin/bash" 51 seconds ago Up 51 seconds 0.0.0.0:22922->22/tcp, :::22922->22/tcp gbmin_node02
90845deed7eb ubuntu:latest "/bin/bash" 55 seconds ago Up 55 seconds 0.0.0.0:11922->22/tcp, :::11922->22/tcp gbmin_node01
- 컨테이너 중지
# docker stop gbmin_node03
- 컨테이너 구동
# docker start gbmin_node01
# docker start gbmin_node02
- 컨테이너 삭제
# docker rm gbmin_node03
gbmin_node03
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
65c257fde766 ubuntu:latest "/bin/bash" 2 minutes ago Up 2 minutes 0.0.0.0:22922->22/tcp, :::22922->22/tcp gbmin_node02
90845deed7eb ubuntu:latest "/bin/bash" 2 minutes ago Up 2 minutes 0.0.0.0:11922->22/tcp, :::11922->22/tcp gbmin_node01
- 컨테이너 콘솔 접속
# docker attach gbmin_node01
root@node01:/#
7. Docker Network 관리
- 네트워크 목록 확인
# docker network ls
NETWORK ID NAME DRIVER SCOPE
1f0b4823faf0 bridge bridge local // 네트워크 지정 없이 생성 하면 기본적으로 bridge 로 할당된다.
485b7bd176ad host host local
64c141eb4ae1 none null local
- 고정 아이피 사용을 위한 네트워크 설정
- 네트워크는 192.168.10.0/24를 사용한다고 가정한다.
- 미리 대역을 확보하고 가상 네트워크를 생성해 컨테이너에 할당해 사용하는 방식으로 사용한다.
- 정적 아이피를 컨테이너에 할당 때는 default 네트워크에 아이피대역을 할당해 사용할 수 없기 때문에 별도로 네트워크 드라이버를 생성해줘야 한다.
- 네트워크 생성
# docker network create -d macvlan --subnet 192.168.10.0/24 --gateway 192.168.10.1 -o parent=eth0 gbmin_node
a9120f3b7a2a5a769ee6c8b011f28fe59159de1e12aac671e4c21a7d25191a0f
- 네트워크 생성 확인
# docker network ls
NETWORK ID NAME DRIVER SCOPE
1f0b4823faf0 bridge bridge local
a9120f3b7a2a gbmin_node macvlan local >> 네트워크 생성
485b7bd176ad host host local
64c141eb4ae1 none null local
- docker 컨테이너 생성 시 아이피 할당 방법
# docker run -it --net gbmin_node --ip 192.168.10.3 --hostname node03.gbminnote.com --name gbmin_node03 --restart always ubuntu:latest /bin/bash
8. Docker file
Dockerfile은 Docker 이미지를 생성하기 위한 설정 파일이다. Dockerfile에는 컨테이너에서 실행될 컨테이너에서 해야 할 작업을 명시할 수 있으며 애플리케이션의 설정과 종속성에 대한 정보를 포함할 수 있다. Dockerfile을 사용하면 애플리케이션을 빌드하고 배포하는 과정을 자동화할 수 있다.
- Dockerfile 빌드 방법
/root/는 Dockerfile 파일 이 있는 경로로 지정하면 된다.
# docker build -t "rockylinux/rockylinux:9" /root/
- Dockerfile 구성요소
- FROM: 이 Dockerfile이 기반으로 사용할 기존 Docker 이미지를 지정한다.
ex) FROM ubuntu:18.04 - RUN: 이미지를 빌드할 때 실행할 쉘 명령을 지정합니다. 이 명령은 이미지에 영구적으로 적용.
ex) RUN apt-get update && apt-get install -y python3 - CMD: 컨테이너가 시작될 때 실행할 기본 명령을 지정합니다. CMD 명령은 Dockerfile에 하나만 포함될 수 있다.
ex) CMD ["echo", "Hello, World!"] - ENTRYPOINT: CMD와 비슷하지만, ENTRYPOINT는 Docker 컨테이너를 실행할 때 항상 사용되는 기본 명령을 지정한다.
ex) ENTRYPOINT ["python3", "-m", "http.server", "8080"] - ENV: 환경 변수를 설정.
ex) ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 - ADD, COPY: 호스트 시스템에서 파일 또는 디렉터리를 Docker 컨테이너에 추가한다. ADD는 URL과 압축 파일도 지원하며, COPY는 단순한 파일/디렉터리 복사에 사용된다.
ex) ADD . /app 또는 COPY . /app - WORKDIR: 작업 디렉터리를 설정. RUN, CMD, ENTRYPOINT, COPY, ADD 명령은 이 디렉터리에서 실행된다.
ex) WORKDIR /app - EXPOSE: Docker 컨테이너에서 사용할 네트워크 포트를 지정.
ex) EXPOSE 8080
- FROM: 이 Dockerfile이 기반으로 사용할 기존 Docker 이미지를 지정한다.
- Dockerfile 예시
# Nginx
#
# VERSION 0.0.1
FROM ubuntu
LABEL Description="This image is used to start the foobar executable" Vendor="ACME Products" Version="1.0"
RUN apt-get update && apt-get install -y inotify-tools nginx apache2 openssh-server
# Firefox over VNC
#
# VERSION 0.3
FROM ubuntu
# Install vnc, xvfb in order to create a 'fake' display and firefox
RUN apt-get update && apt-get install -y x11vnc xvfb firefox
RUN mkdir ~/.vnc
# Setup a password
RUN x11vnc -storepasswd 1234 ~/.vnc/passwd
# Autostart firefox (might not be the best way, but it does the trick)
RUN bash -c 'echo "firefox" >> /.bashrc'
EXPOSE 5900
CMD ["x11vnc", "-forever", "-usepw", "-create"]
# Multiple images example
#
# VERSION 0.1
FROM ubuntu
RUN echo foo > bar
# Will output something like ===> 907ad6c2736f
FROM ubuntu
RUN echo moo > oink
# Will output something like ===> 695d7793cbe4
# You'll now have two images, 907ad6c2736f with /bar, and 695d7793cbe4 with
# /oink.
9. Docker Hub
Docker Hub는 Docker 이미지를 저장, 공유, 배포하기 위한 클라우드 기반 레지스트리 서비스다. 개발자들은 Docker Hub를 통해 자신들의 이미지를 업로드하고 공유하거나, 다른 사람들이 만든 이미지를 찾아서 다운로드할 수 있다.
- Docker Hub의 주요 특징
- 공개 및 개인 저장소: Docker Hub에는 수백만 개의 이미지가 포함된 공개 저장소가 있다. 이 공개 저장소를 통해 누구나 다양한 종류의 Docker 이미지를 무료로 다운로드하고 사용할 수 있다. 또한, 개인적인 사용 또는 팀 내에서만 공유하려는 이미지를 위해 개인 저장소를 생성하고 사용할 수 있습니다. 개인 저장소는 무료로 한 개까지 생성할 수 있으며, 추가 저장소는 유료로 결제 후 이용 가능하다.
- 자동 빌드 및 웹훅: Docker Hub는 GitHub 또는 Bitbucket과 같은 코드 호스팅 서비스와 연동하여 Dockerfile의 변경을 감지하고 자동으로 Docker 이미지를 빌드하고 업데이트하는 기능을 제공한다. 또한, 이미지 빌드가 완료되면 특정 작업을 자동으로 실행하는 웹훅(webhook) 기능도 제공한다.
- 공동 작업 : Docker Hub를 통해 여러 사용자를 하나의 그룹으로 관리하고, 그룹 내에서 이미지에 대한 액세스 권한을 제어할 수 있다.
- 사이트
- docker 컨테이너 이미지 다운로드 방법
회원 가입 후 로그인 한다. 가입 자체는 무료다.
Explore 메뉴 접속 하면 수천 개 이미지가 존재함.
저장소 상세 정보를 보면 이미지에 대한 설명과 사용 방법 이미지 다운로드 커맨드를 확인할 수 있다.
- 개인저정소생성 방법
개인 저장소는 Repositories 메뉴에서 생성 가능하다.
프라이빗 저장소는 기본적으로 1개만 무료로 저장되고 여러 개 생성 시 결제해야 한다.
저장소 생성 완료
- 저장소에 이미지 올리기
업로드할 이미지 생성
docker commit [옵션] 컨테이너_이름 또는_컨테이너_ID [저장될_이미지_이름]:[태그]
docker tag 설정
# docker tag gbmin_node01:0627 gbmin/gbmin_node01:0627
gbminnote:~# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
gbmin/gbmin_node01 0627 f5756a512457 11 minutes ago 229MB << 업로드할 이미지 생성
ubuntu latest 99284ca6cea0 3 weeks ago 77.8MB
rockylinux/rockylinux 9 175264fac6da 6 weeks ago 176MB
Docker Hub 로그인
# docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: ************
Password: *************
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Docker image push
# docker push gbmin/gbmin_node01:0627
The push refers to repository [docker.io/gbmin/gbmin_node01]
c57a95f9551e: Pushed
cdd7c7392317: Mounted from library/ubuntu
0627: digest: sha256:3e722bc8aa1e96c9487aba0f8a674610dfb86d3127c629d6e61c1a0ca14f48d4 size: 741
- Docker Hub 업로드 이미지 확인
- 업로드된 이미지 다운로드
# docker push gbmin/gbmin_node01:tagname
The push refers to repository [docker.io/gbmin/gbmin_node01]
tag does not exist: gbmin/gbmin_node01:tagname
Docker에 대한 문서를 다시 살펴보니, Windows와 Mac 운영 체제를 위한 애플리케이션 엔진이 함께 제공된다는 것을 알게 되었다 Docker가 처음 소개된 지 약 10년 전이었던 것으로 기억하는데 여전히 많은 환경에서 사용되고 있으며, 그 지원 영역이 계속 넓어지고 있다는 것을 의미하는 것 같다. Docker의 등장은 개발자들이 소프트웨어를 개발하는 방식에 많은 변화를 가져왔다고 생각한다. 개발자라면 Docker에 대한 이해와 관심 가져보는 것도 많은 도움이 될 것 같다.