티스토리 뷰
서론
앞선 포스팅에서 docker save와 docker load 그리고 docker export와 docker import 명령어를 사용하는 방법에 대해 살펴보았습니다.
[Docker Command] docker 명령어 뽀개기
간단히 명령어에 대해 리마인드를 진행해 보자면 다음과 같습니다.
1) docker save / load (docker image를 tar 파일로 추출)
[root@CIServer sysconfig]# docker save https:v1.1 -o save.tar
[root@CIServer sysconfig]# ls -la save.tar
-rw-------. 1 root root 167019008 Dec 2 01:08 save.tar
[root@CIServer sysconfig]# docker load -i save.tar
Loaded image: https:v1.1
[root@CIServer sysconfig]#
docker save와 load를 사용하여 docker 이미지를 추출하고 로드할 수 있습니다.
2) docker export / import (docker image와 container를 tar 파일로 추출)
[root@CIServer sysconfig]# docker export myapache >> apache.tar
[root@CIServer sysconfig]# ls -la apache.tar
-rw-r--r--. 1 root root 167010816 Dec 2 00:43 apache.tar
[root@CIServer sysconfig]# docker import apache.tar https:v1.1
sha256:35b0914eb5716b6ad7bffbe7ae5601ee65d5468bb65473c0568c4624dd507748 [root@CIServer sysconfig]# docker export a7fce4baf6a6 | docker import - httpd:v1.1
sha256:83db3564935410c73aa5c5721dc93ec87ad58b4ee690873914298ba6d624e24c
[root@CIServer sysconfig]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
httpd v1.1 83db35649354 7 seconds ago 162 MB
httpd v1.0 0fe8bdfe6399 58 minutes ago 165 MB
docker.io/httpd latest 2ae34abc2ed0 2 days ago 165 MB
docker.io/jenkins latest cd14cecfdb3a 16 months ago 696 MB
[root@CIServer sysconfig]#
docker export와 import 명령어를 통해 docker image 뿐 아니라 기동 중인 docker container를 tar 파일로 추출하고 로드할 수 있습니다.
위와 같이 명령어를 활용하여 docker images와 docker container를 저장하고 또 다른 환경으로 이관할 수 있습니다.
본 포스팅에서는 두가지 명령어의 차이점에 대해 살펴보고 활용방안에 대해 알아보겠습니다.
본론
먼저 docker save와 docker load에 대해 살펴보겠습니다.
1) docker save/load & docker export/import 비교
docker save와 load 명령어는 현재 docker local repository에 있는 docker image를 tar 파일로 추출하고 다시 로드하는 명령어입니다.
docker image를 조작하지 않고 단순히 또 다른 환경으로 이관하기 위한 용도로 사용할 수 있습니다. 즉 docker save로 추출된 이미지는 original 도커 이미지와 동일한 이미지라고 할 수 있습니다.
2) docker layer 비교
docker export 명령어를 수행하여 tar 파일을 추출할 경우, docker save와 같이 tar 파일로 추출하게 되지만, docker의 layer에 대한 정보는 포함하지 않습니다.
다음은 jupyterhub를 구성하기 위한 tljh-systemd 이미지에 대한 비교 내용입니다.
[tljh jupyterhub original image inspect info]
[
{
"Id": "sha256:000b57f055093807652dfe4a5a48b159f3283c724929336aaed21dae83601290",
"RepoTags": [
"192.168.2.151:13000/jupyterpackage/jupyterhub/tljh:latest",
"tljh-systemd:latest"
],
"RepoDigests": [
"192.168.2.151:13000/jupyterpackage/jupyterhub/tljh@sha256:1996857e56912ddd3c22f1c18a59d486d8a3db2d6bf6759e21d7a5d8048af392"
],
"Parent": "sha256:793b2fec2967b335e80d19c3e1638b448e7d388a16c7eab40f725985e1e33eae",
"Comment": "",
"Created": "2020-02-05T00:45:22.847616558Z",
"Container": "0bd70d1bed16a90b5543078d95f91411dca3975ac9189771d070b76f933eb155",
"ContainerConfig": {
"Hostname": "kubemaster",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/opt/tljh/hub/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"TLJH_BOOTSTRAP_DEV=yes",
"TLJH_BOOTSTRAP_PIP_SPEC=/srv/src"
],
"Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
"CMD [\"/bin/bash\" \"-c\" \"exec /sbin/init --log-target=journal 3>&1\"]"
],
"Image": "sha256:793b2fec2967b335e80d19c3e1638b448e7d388a16c7eab40f725985e1e33eae",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {},
"StopSignal": "SIGRTMIN+3"
},
"DockerVersion": "19.03.5",
"Author": "",
"Config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/opt/tljh/hub/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"TLJH_BOOTSTRAP_DEV=yes",
"TLJH_BOOTSTRAP_PIP_SPEC=/srv/src"
],
"Cmd": [
"/bin/bash",
"-c",
"exec /sbin/init --log-target=journal 3>&1"
],
"Image": "sha256:793b2fec2967b335e80d19c3e1638b448e7d388a16c7eab40f725985e1e33eae",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": null,
"StopSignal": "SIGRTMIN+3"
},
"Architecture": "amd64",
"Os": "linux",
"Size": 274298992,
"VirtualSize": 274298992,
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/a35df2529261b6734e9c9b28be0ec8f2da19d3ba1dabe5f1898b7f0959a6bee2/diff:/var/lib/docker/overlay2/9b93fe435a173b56a5e66125c9e8107203994b818d305f276985c91eb25d0f74/diff:/var/lib/docker/overlay2/2ff9bc616de54f909f06537873d2e769b5e186a7053d0ac9c3e79490b594d6b8/diff:/var/lib/docker/overlay2/4f58322c86837c3abb0113e5eb8587332aa8043d505d8b4cf96cf74b9ae97b76/diff:/var/lib/docker/overlay2/b1c9694245f004c3e0ac72644a0265fc6295f1b42489cddb936554d1d7cf23fc/diff:/var/lib/docker/overlay2/df0b89fd1b8bdd64272491aa7ecf6f5fc987a8dd67264c314315fa69a9e59d96/diff:/var/lib/docker/overlay2/03e4a35a62cce7887ce6bd238450b50425e2a2898b939bea16934227e64db8e0/diff",
"MergedDir": "/var/lib/docker/overlay2/a04c8bc2ffb37d5470c7df121ea09ef252fa0fa83cfb367f34cc09d98c547471/merged",
"UpperDir": "/var/lib/docker/overlay2/a04c8bc2ffb37d5470c7df121ea09ef252fa0fa83cfb367f34cc09d98c547471/diff",
"WorkDir": "/var/lib/docker/overlay2/a04c8bc2ffb37d5470c7df121ea09ef252fa0fa83cfb367f34cc09d98c547471/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:43c67172d1d182ca5460fc962f8f053f33028e0a3a1d423e05d91b532429e73d",
"sha256:21ec61b65b20ec53a1b7f069fd04df5acb0e75434bd3603c88467c8bfc80d9c6",
"sha256:1d0dfb259f6a31f95efcba61f0a3afa318448890610c7d9a64dc4e95f9add843",
"sha256:f55aa0bd26b801374773c103bed4479865d0e37435b848cb39d164ccb2c3ba51",
"sha256:50395ecc5afcc0ab36db7b7e50e9084a613b4d2c138aa27713a5118d2c63849f",
"sha256:a8fda65e8b5f4c0d74dd8837c4307bed27f4cd3d17624f03769cb824616379a5",
"sha256:3c6d8ec6e3141e5fc66c96cbb171ffc2c5aa2509709f6faefdf042f9d2ada3ee",
"sha256:755886c83cb21a430d651f2e7240ef94d6ec5d722cb2aa7f6e5aaaf474fcbb1c"
]
},
"Metadata": {
"LastTagTime": "2020-02-05T09:46:09.767647815+09:00"
}
}
]
위와 같이 해당 docker file의 Layers는
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:43c67172d1d182ca5460fc962f8f053f33028e0a3a1d423e05d91b532429e73d",
"sha256:21ec61b65b20ec53a1b7f069fd04df5acb0e75434bd3603c88467c8bfc80d9c6",
"sha256:1d0dfb259f6a31f95efcba61f0a3afa318448890610c7d9a64dc4e95f9add843",
"sha256:f55aa0bd26b801374773c103bed4479865d0e37435b848cb39d164ccb2c3ba51",
"sha256:50395ecc5afcc0ab36db7b7e50e9084a613b4d2c138aa27713a5118d2c63849f",
"sha256:a8fda65e8b5f4c0d74dd8837c4307bed27f4cd3d17624f03769cb824616379a5",
"sha256:3c6d8ec6e3141e5fc66c96cbb171ffc2c5aa2509709f6faefdf042f9d2ada3ee",
"sha256:755886c83cb21a430d651f2e7240ef94d6ec5d722cb2aa7f6e5aaaf474fcbb1c"
]
},
총 8단계로 나뉘어 구성되어 있습니다.
이를 docker export로 추출한 이미지를 import한 docker image와 비교해 보도록 하겠습니다.
[tljh jupyterhub import image inspect info]
[
{
"Id": "sha256:416397accdf22e543315dbd9a8fdeb3f6f54ab4f009e57695495c823eb5bda62",
"RepoTags": [
"192.168.2.151:13000/jupyterhub/tljh_add_bootstrap:v1.0"
],
"RepoDigests": [],
"Parent": "",
"Comment": "Imported from -",
"Created": "2020-02-05T02:21:19.149160748Z",
"Container": "",
"ContainerConfig": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": null,
"Cmd": null,
"Image": "",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": null
},
"DockerVersion": "18.09.7",
"Author": "",
"Config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": null,
"Cmd": null,
"Image": "",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": null
},
"Architecture": "amd64",
"Os": "linux",
"Size": 2120217745,
"VirtualSize": 2120217745,
"GraphDriver": {
"Data": {
"MergedDir": "/var/lib/docker/overlay2/ef7582ee39c4246459fe63f924cb5c32230b71eae36437244947c1df11b77d86/merged",
"UpperDir": "/var/lib/docker/overlay2/ef7582ee39c4246459fe63f924cb5c32230b71eae36437244947c1df11b77d86/diff",
"WorkDir": "/var/lib/docker/overlay2/ef7582ee39c4246459fe63f924cb5c32230b71eae36437244947c1df11b77d86/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:e5fc2009202763467fc51b8976c72cc178954d265ec7d9d55caa71324818157a"
]
},
"Metadata": {
"LastTagTime": "2020-02-05T11:21:19.166191386+09:00"
}
}
]
import로 로드한 이미지의 Layers 정보는
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:e5fc2009202763467fc51b8976c72cc178954d265ec7d9d55caa71324818157a"
]
},
동일한 이미지 임에도 불구하고 위와 같이 하나로 통합된 것을 확인할 수 있습니다.
이를 통해 docker export 명령어는 현재 docker container 내부의 디렉토리 전체를 압축하여 새로운 이미지로 생성해 준다고 볼 수 있습니다.
3) docker export/import 한 이미지 기동
그럼 docker import로 로드한 이미지를 기동해 보도록 하겠습니다.
기존 오리지날 jupyterhub 기동에 사용했던 명령어를 그대로 입력해 보도록 하겠습니다.
[root@CIServer the-littlest-jupyterhub]# docker run --privileged --detach --name=tljh-dev --publish 12000:80 --mount type=bind,source=$(pwd),target=/srv/src 192.168.2.151:13000/jupyterhub/tljh_add_bootstrap:v1.0
docker: Error response from daemon: No command specified.
See 'docker run --help'.
[root@CIServer the-littlest-jupyterhub]#
docker run을 수행하였지만, 위와 같은 에러 메시지를 받게됩니다.
docker: Error response from daemon: No command specified.
여기서 살펴볼 점은 바로 도커 export로 추출하여 로드한 docker image의 경우 docker container를 단순히 아카이빙 한 이미지 라는 것입니다. 즉 압축한 파일 자체를 이미지로 로드해 둔 것이라고 볼 수 있습니다.
이를 정상적으로 기동하기 위해서는 import 이미지를 기반으로 새롭게 Dockerfile을 작성하거나, import 시점에 명령어를 주입시켜 주어야 합니다.
[root@CIServer ~]# docker import --change 'CMD ["/bin/bash","-c","exec /sbin/init --log-target=journal 3>&1"]' tljh.tar 192.168.2.151:13000/jupyterhub/tljh_add_bootstrap:v1.0
sha256:045273611b2cb6febc9778c9a06b8f57c97e988a6757ab950fc0023592bcfd35
[root@CIServer ~]#
위와 같이 docker import --change 옵션을 사용하여 필요한 정보들을 기입합니다.
--change 옵션은 Dockerfile에 기입할 내용을 import 시점에 옵션으로 등록할 수 있습니다.
기존 Original Docker file의 CMD에 정의 된 아래 내용을 기반으로
"Cmd": [
"/bin/bash",
"-c",
"exec /sbin/init --log-target=journal 3>&1"
],
--change CMD ["/bin/bash","-c","exec /sbin/init --log-target=journal 3>&1"] 옵션을 추가하면 import 시점에 Dockerfile의 CMD를 추가한 것과 같이 동작하게 됩니다.
[root@CIServer the-littlest-jupyterhub]# docker import --change 'CMD ["/bin/bash","-c","exec /sbin/init --log-target=journal 3>&1"]' tljh.tar 192.168.2.151:13000/jupyterhub/tljh_add_bootstrap:v1.0
sha256:045273611b2cb6febc9778c9a06b8f57c97e988a6757ab950fc0023592bcfd35
[root@CIServer the-littlest-jupyterhub]# docker run --privileged --detach --name=tljh-dev --publish 12000:80 --mount type=bind,source=$(pwd),target=/srv/src 192.168.2.151:13000/jupyterhub/tljh_add_bootstrap:v1.0
716291ec798118d7a1793d5da41a4c20fe8792d924929ae35ad2e357cee635f7
[root@CIServer the-littlest-jupyterhub]# docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
716291ec7981 192.168.2.151:13000/jupyterhub/tljh_add_bootstrap:v1.0 "/bin/bash -c 'exec …" 5 seconds ago Up 3 seconds 0.0.0.0:12000->80/tcp tljh-dev
[root@CIServer the-littlest-jupyterhub]#
위와 같이 Docker Container가 정상 기동 된 것을 확인할 수 있습니다.
결론
지금까지 살펴본 내용을 정리하자면 다음과 같습니다.
1) docker save & docker load : docker image를 tar 파일로 추출하고 로드하는 역할로 이미지에 변경이 있지 않은 오리지널 이미지와 동일하다.
2) docker export & docker import : docker container를 tar 파일로 추출하고 로드하는 역할로 오리지널 이미지를 아카이빙하여 하나의 layer로 저장된 이미지를 생성한다.
3) docker export & docker import로 로드한 이미지를 기동하기 위해서는 Dockerfile을 작성하거나, import --change 옵션을 사용하여 필요한 구문을 추가해야 한다.
위와 같은 결론을 기반으로 명령어를 활용하자면, Docker Image를 단순히 옮기고 싶을 경우에는 docker save를 Container에 커스터마이징 된 정보를 기반으로 Container를 이미지로 생성하고 싶을 경우에는 docker export를 활용할 수 있을 것입니다.
'③ 클라우드 > ⓓ Docker' 카테고리의 다른 글
[Docker Image] 취약점 분석 (Anchore opensource) (0) | 2020.05.30 |
---|---|
도커 이미지 관리를 위한 Garbage Collection (Docker GC) (0) | 2020.03.12 |
Docker Container - Status Exited (n) Code 알아보기 (0) | 2019.12.27 |
[Docker] Kubernetes 보안 (Cgroup) (1) | 2019.10.11 |
[Docker Command] docker 명령어 뽀개기 (1) | 2019.09.04 |
- Total
- Today
- Yesterday
- 쿠버네티스
- Architecture
- OpenStack
- TA
- 마이크로서비스
- Docker
- SWA
- Da
- JEUS7
- openstack tenant
- kubernetes
- SA
- k8s
- JBoss
- aa
- openstack token issue
- 아키텍처
- MSA
- jeus
- apache
- wildfly
- git
- 오픈스택
- webtob
- 마이크로서비스 아키텍처
- nodejs
- aws
- JEUS6
- API Gateway
- node.js
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |