
해당 애플리케이션이 가지고 있는 docs 파일을 보는게 좋다.
Docker docs를 살펴보자! https://docs.docker.com/reference/
Docker 주요 관리 대상 : container, image, network, data volumes(Linux에서의 nfs 같은 기능)
컨테이너의 실체
1 ) image의 snapshot이다. -> /var/lib/docker ~
2 ) process다.image 관련 명령 / container 관련 명령
docker image ~
docker (container) ~
- docker pull : 도커 허브 레지스트리에서 로컬로 도커 이미지 내려받기
- docker push : 로컬에 있는 도커 이미지를 도커 허브 레지스트트리에 업로드하기
- docker login : 업로드 하기 전 도커 허브 계정으로 로그인 수행하기
- docker logout : 도커 허브에서 로그아웃하기
docker pull을 하기 전에 hub.docker.com에서 해당 image 정보를 확인해야 한다. ( latest는 비추! )
docker pull을 통해 다운로드 한다.
docker pull 할 때 바로 이미지명을 쓰는 것이 당연한 것은 아니다.
docker hub가 아닌 다른 레지스트리를 사용한다면 주소를 명시해주어야 한다.
## docker hub를 사용한다면 앞에 주소 생략 가능
## 원래 명령어 : docker pull docker.io/library/mongo:5
kevin@hostos1:~$ docker pull mongo:5
## 아래 주소를 가리키고 있음
## docker 소프트웨어가 docker hub를 바라보고 있다
kevin@hostos1:~$ docker info | grep -i registr
Registry: https://index.docker.io/v1/
Insecure Registries:
## cloud 레지스트리 경우
## 외부 registry를 사용하면 앞에 주소를 명시해주어야 함
## 웹 주소 URL에서 도메인 주소의 시작인 http:// 붙이지 않고, 이미지 주소를 써야 함
kevin@hostos1:~$ docker pull gcr.io./google-samples/hello-app:1.0
## private 레지스트리 사용할 경우
kevin@hostos1:~$ 192.168.56.200:5000/myweb:1.0
kevin@hostos1:~$ docker pull httpd:2.4
2.4: Pulling from library/httpd
## Already exists가 있으면 이미 해당 레이어가 이미 있다는 의미
7a6db449b51b: Already exists
b4effd428409: Pull complete
6b29c2b62286: Pull complete
c2123effa3fc: Pull complete
152876b0d24a: Pull complete
Digest: sha256:b418eccc8ec9a04dc07596aef200edfa4d2020dc1168654d6a17af145c33cae6
Status: Downloaded newer image for httpd:2.4
docker.io/library/httpd:2.4
## 이미지 용량 확인
## 2 weeks ago : 2주 전에 업데이트 했다는 의미
## 이미지명, 태그, 아이디, 업데이트시기, 용량
kevin@hostos1:~$ docker images | grep httpd
httpd 2.4 a981c8992512 2 weeks ago 145MB
도커 오브젝트(이미지, 컨테이너)에 대한 세부 정보 조회를 할 수 있다.
물리적으로 host os에 저장된 영역을 이용한다.
## 해당 이미지 포트 확인
## httpd 포트 확인, EXPOSE를 통해서 포트가 80인것을 확인
## 용량 중에 숫자 있는 것 = 레이어의 개수
## CREATED BY 도커 명령어 -> 잘려서 나옴
kevin@hostos1:~$ docker image history httpd:2.4
IMAGE CREATED CREATED BY SIZE COMMENT
a981c8992512 2 weeks ago /bin/sh -c #(nop) CMD ["httpd-foreground"] 0B
<missing> 2 weeks ago /bin/sh -c #(nop) EXPOSE 80 0B
<missing> 2 weeks ago /bin/sh -c #(nop) COPY file:c432ff61c4993ecd… 138B
<missing> 2 weeks ago /bin/sh -c #(nop) STOPSIGNAL SIGWINCH 0B
<missing> 2 weeks ago /bin/sh -c set -eux; savedAptMark="$(apt-m… 59.9MB
<missing> 2 weeks ago /bin/sh -c #(nop) ENV HTTPD_PATCHES= 0B
<missing> 2 weeks ago /bin/sh -c #(nop) ENV HTTPD_SHA256=eb397fee… 0B
<missing> 2 weeks ago /bin/sh -c #(nop) ENV HTTPD_VERSION=2.4.54 0B
<missing> 2 weeks ago /bin/sh -c set -eux; apt-get update; apt-g… 4.76MB
<missing> 2 weeks ago /bin/sh -c #(nop) WORKDIR /usr/local/apache2 0B
<missing> 2 weeks ago /bin/sh -c mkdir -p "$HTTPD_PREFIX" && chow… 0B
<missing> 2 weeks ago /bin/sh -c #(nop) ENV PATH=/usr/local/apach… 0B
<missing> 2 weeks ago /bin/sh -c #(nop) ENV HTTPD_PREFIX=/usr/loc… 0B
<missing> 3 weeks ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 3 weeks ago /bin/sh -c #(nop) ADD file:7726efb0e0eb5003d… 80.4MB
## 도커 명령어 전체 보기
kevin@hostos1:~$ docker image history httpd:2.4 --no-trunc > httpd_dockerfile.txt
# 다운로드한 이미지 상세 정보 조회
root@hostos1:~# docker image inspect httpd:2.4
...
"Container": "91961c32bbf7467a5b882d5f39b01db2cdb1c01cf360e961905945314a47d5ba",
...
이미지를 조회하는데 container 정보도 볼 수 있다.
왜? Dockerfile로 image build를 통해 image를 생성한다.
Dockerfile에서 라인 수 -> Step -> layer을 나타낸다.
image는 불변이고, Container만 수정이 가능하다.
따라서 build 과정은 image -> Container -> image -> Container ...의 반복을 하면서 최종 image가 만들어지게 된다.
위에서 나타난 Container는 마지막 Container를 가리킨다.
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/9ff75a65eb6c48e7d15a82b663b9321dda7f505f6f2f3066c099b32c77780e2c/diff:/var/lib/docker/overlay2/a0eb62c6e0ee8715c490ba2dc05b20dbf23bf23ccb566f2718024bf378b1300d/diff:/var/lib/docker/overlay2/fc40606b6977c7b2205cdbb1a900b5534f33ce1351b9e6f94dc6beb4f50c2638/diff:/var/lib/docker/overlay2/001f1f03144d34fd63b9cea784ef159a624522fdaeb28ea20480deced019563b/diff",
"MergedDir": "/var/lib/docker/overlay2/bdeb451dd4092720d20182683fb67822826d211c625d6b4f7077506eb12663c0/merged",
"UpperDir": "/var/lib/docker/overlay2/bdeb451dd4092720d20182683fb67822826d211c625d6b4f7077506eb12663c0/diff",
"WorkDir": "/var/lib/docker/overlay2/bdeb451dd4092720d20182683fb67822826d211c625d6b4f7077506eb12663c0/work"
},
"Name": "overlay2"
},
각 Dir이 무엇을 의미하는지 알아보자.
inspect는 format을 이용해서 지정한 형식의 정보만 출력할 수 있다.
계층 형식으로 되어 있어 하위 정보 조회 시 .상위[.하위] 방식으로 조회가 가능하다.
kevin@hostos1:~$ docker image inspect --format="{{ .Config.ExposedPorts }}" httpd:2.4
map[80/tcp:{}]
kevin@hostos1:~$ docker image inspect --format="{{ .ContainerConfig.Env }}" httpd:2.4
[PATH=/usr/local/apache2/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HTTPD_PREFIX=/usr/local/apache2 HTTPD_VERSION=2.4.54 HTTPD_SHA256=eb397feeefccaf254f8d45de3768d9d68e8e73851c49afd5b7176d1ecf80c340 HTTPD_PATCHES=]
## 두개 다 보기
kevin@hostos1:~$ docker image inspect --format="{{ .Config.ExposedPorts }} {{ .ContainerConfig.Env }}" httpd:2.4
map[80/tcp:{}] [PATH=/usr/local/apache2/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HTTPD_PREFIX=/usr/local/apache2 HTTPD_VERSION=2.4.54 HTTPD_SHA256=eb397feeefccaf254f8d45de3768d9d68e8e73851c49afd5b7176d1ecf80c340 HTTPD_PATCHES=]
## ipaddress 대소문자 구분 없이 찾기
kevin@hostos1:~$ docker inspect py-test | grep -i ipaddress
"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.10",
"IPAddress": "172.17.0.10",
kevin@hostos1:~$ docker inspect py-test | grep -i mac
"MacAddress": "02:42:ac:11:00:0a",
"MacAddress": "02:42:ac:11:00:0a",
kevin@hostos1:~$ docker search httpd

도커 이미지를 실행하면 여러 개의 컨테이너를 구동할 수 있다.
처음 내려받은 이미지는 수백 메가 용량을 가지고 있지만 컨테이너를 구동할 때마다 이미지를 내려받지 않고 로컬에 저장된 이미지를 계속 사용한다.
## 도커의 모든 데이터 및 로그 정보는 다음과 같은 경로에 저장됨
kevin@hostos1:~/LABs/nginx-test$ sudo su -
root@hostos1:~# cd /var/lib/docker/
root@hostos1:/var/lib/docker# ls
buildkit containers image network overlay2 plugins runtimes swarm tmp trust volumes
로컬에서 httpd 레이어를 추적해서 그 위치를 파악하고 컨테이너가 그 레이어에서 수행되는 것을 확인할 수 있다.
여러 레이어로 구성된 이미지는 몇 개의 컨테이너를 실행해도 별도의 읽고 쓰기가 가능한 컨테이너 레이어가 상위에 추가되므로 하위 이미지 레벨의 레이어에는 영향을 주지 않으면서 동작하는 것이 컨테이너의 가상화!
태그는 업로드할 주소 입력을 위해 작성한다.
도커 태그는 원본 이미지에 참조 이미지 이름을 붙이는 명령이다.
이미지 ID는 변경되지 않는다. 버전 관리를 위해 활용한다.
docker push 계정 ID / 저장소 : 태그 -> jjy9922/이미지명:버전 -> 주소
## 이미지 ID에 세부 정보를 붙여 태그 지정
## 아이디 변경되지 않음
root@hostos1:/var/lib/docker# docker image tag 86151b7e2661 debian-phpserver:1.0
root@hostos1:/var/lib/docker# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
phpserver 1.0 86151b7e2661 11 hours ago 410MB
debian-phpserver 1.0 86151b7e2661 11 hours ago 410MB
## 도커 허브와 같은 레지스트리에 업로드하는 경우 저장소명과 함께 태그 지정
root@hostos1:/var/lib/docker# docker image tag debian-phpserver:1.0 jjy9922/debian-phpserver:3.0
root@hostos1:/var/lib/docker# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
jjy9922/debian-phpserver 3.0 86151b7e2661 11 hours ago 410MB
root@hostos1:/var/lib/docker# docker login
Login Succeeded

root@hostos1:~# docker push jjy9922/myweb:1.0
## 본인이 업로드한 이미지 다운
kevin@hostos2:~$ docker pull jjy9922/myweb:1.0
1.0: Pulling from jjy9922/myweb
213ec9aee27d: Pull complete
2546ae67167b: Pull complete
23b845224e13: Pull complete
9bd5732789a3: Pull complete
328309e59ded: Pull complete
b231d02e5150: Pull complete
7e9531876764: Pull complete
93be49f53300: Pull complete
본인이 베이스 이미지에 특성 애플리케이션을 서비스와 코드 등을 포함해 컨테이너로 실행한 경우, docker commit 명령을 통해 컨테이너를 이미지로 저장할 수 있다.
도커 허브로 원격 접속하기 위해서 두 가지 방법이 있다.
## 방법 1 ) 아이디, 비번 입력하고 원격 접속 성공
kevin@hostos1:~$ 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: jjy9922
Password:
## 출력된 경고를 보면 암호화되지 않고 아래 경로에 암호가 저장되어 있다고 함
## 암호화가 알고리즘이 아닌 base24 인코딩을 통해 암호 키 값이 저장되어 있기 때문
WARNING! Your password will be stored unencrypted in /home/kevin/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
## base64는 디코딩이 가능하므로 노출에 주의해야 함!
kevin@hostos1:~$ cat ~/.docker/config.json
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "amp5OTkyMjp3bGRQMDEwISEh"
}
}
## 현재 접속 사용자 조회
kevin@hostos1:~$ docker info | grep Username
Username: jjy9922
## docker logout을 하면 config.json auth 값이 삭제되고, docker info에서도 사용자명이 제거됨
## 방법 2 ) hub.docker.com 사이트에서 제공하는 액세스 토큰 이용
## 복사한 액세스 토큰 복붙
kevin@hostos1:~$ vi .access_token
## 별도의 암호 입력 없이 액세스 토큰을 이용해 로그인 됨
kevin@hostos1:~$ cat .access_token | docker login --username jjy9922 --password-stdin
용량 관리를 위해 docker image save를 통해 이미지를 백업하거나 주기적으로 업무에 사용하는 이미지와 사용하지 않은 이미지를 구분하여 관리하고, 불필요한 이미지는 삭제하는 것이 좋다.
docer image rm이고, 단축 명령은 docker rmi 이다.
도커 이미지는 현재 사용 중인 컨테이너가 없으면 바로 삭제된다.
태그가 있는 이미지 원본은 태그된 이미지와 상관없이 삭제할 수 있다.
이름:태그로 붙여주어야 한다. 만약 ID로 삭제할 시 다른 태그가 같은 ID를 참조하고 있으면 오류가 발생한다.
이미지 삭제 전 참조 중인 컨테이너는 없어야 한다.
( 강제 삭제도 가능 --force )
컨테이너가 가동중이면 stop한 뒤 rm을 통해 제거하면 이미지 삭제가 가능하다.
## 이미지 검색
kevin@hostos1:~$ docker images | grep python
python 3.8-slim b0d55d04540d 5 days ago 124MB
## 이미지 삭제 전 오류 확인
## 컨테이너가 있음, 현재 다른 태그 참조로 인한 오류 발생
kevin@hostos1:~$ docker image rm python:3.8-slim
Error response from daemon: conflict: unable to remove repository reference "python:3.8-slim" (must force) - container 19d19e72791f is using its referenced image b0d55d04540d
## 컨테이너 확인
kevin@hostos1:~$ docker ps | grep b0d55d04540d
## 컨테이너 중지
kevin@hostos1:~$ docker stop py-test
py-test
## 컨테이너 삭제
kevin@hostos1:~$ docker rm py-test
py-test
## 삭제 성공
kevin@hostos1:~$ docker image rm python:3.8-slim
Untagged: python:3.8-slim
Untagged: python@sha256:8ae28a791362432b0303d485f4c9fc16479a3254f311728989e23173da9f3341
Deleted: sha256:b0d55d04540d447a64b2ad1e4f40e8b258ee0dcb460277b4c1cda4b713d1f484
Deleted: sha256:3fbe05f3dc4cee4e8871c8e9bb3e16457e73170c661f145a7d3538b57c5ba627
Deleted: sha256:cedbfc834af57a8937732d50ae39953bd79f53e267c71d9dacd0cabc4a72b598
Deleted: sha256:8c7167c74aa8a9c03f2e7ed5e694a81074d504512ebd32c991bb2e6940370328
Deleted: sha256:9db246109d1700e964e54cf78ca23bea08035ba2ff6b9c15cc803bd7dd692cf1
쉘 스크립트의 변수를 사용해서 삭제
## 실행중인 모든 컨테이너 ID만 추출
kevin@hostos1:~$ docker ps -a -q
060eeac691d6
76abae63be1d
3d47c12be695
cb6ed79a6f27
ecf6b42f8ae3
b9cf19b27e1b
a39413680c22
5a68a3cba8cf
a3a9e98581aa
242761fe4f31
06d1c85c1150
a331514cec9e
35ee35ea3bd7
## 죽은 컨테이너 아이디 찾기
kevin@hostos1:~$ docker ps -a -q --filter 'status=exited'
242761fe4f31
## 죽은 아이디만 찾아서 삭제
kevin@hostos1:~$ docker rm $(docker ps -a -q --filter 'status=exited')
242761fe4f31
## 이미지 전체 삭제
kevin@hostos1:~$ docker rmi $(docker images -q)
## alias로 설정해서 바로 사용
kevin@hostos1:~$ vi .bashrc
alias cexrm='docker rm $(docker ps -a -q --filter 'status=exited')'
kevin@hostos1:~$ source .bashrc
kevin@hostos1:~$ cexrm
이미지는 컨테이너 구동을 위해 존재한다.
로컬에 다운로드한 이미지 중 하나 이상의 컨테이너가 연결되지 않은 모든 이미지를 제거해보자.
## -a 옵션을 이용하여 사용 중이 아닌 모든 이미지가 제거됨
kevin@hostos1:~$ docker image prune -a
## 사용중이 아닌 48시간 이전의 모든 이지미를 별도 확인 없이 제거
kevin@hostos1:~$ docker image prune -a -f --filter "until=48h"
Docker CI/CD 워크플로


이미지는 읽기 전용의 불변의 값! 이러한 이미지를 바탕으로 도커 엔진은 컨테이너를 생성할 수 있다. 이때 읽고 쓰기가 가능한 레이어를 추가해서 만들어지는것이 컨테이너다.
컨테이너 명령 대부분은 서비스 실행 및 운영과 관련되어 있다.
도커 이미지를 기반으로 snapshot이 만들어지고, 이 snapshot은 읽기 전용의 도커 이미지 레이어를 복제한 것을 말한다.
그 위에 읽고 쓰기가 가능한 컨테이너 레이어를 결합하면 컨테이너가 된다.
도커 이미지 복사본 snapshot 레이어 위에 읽고 쓰기가 가능한 컨테이너 레이어를 추가한 뒤 docker start로 컨테이너를 시작한다.
이렇게 실행된 컨테이너를 docker ps 명령을 통해 조회한다.
( 리눅스에서 process 조회, 컨테이너도 프로세스다! )
docker run = [ pull ] + create + start + [ command ]
docker run은 마지막에 작성한 이미지가 로컬에 없다면 pull까지 해준다.
참고 ) 쿠버에서 위 명령어를 kubectl로 사용한다.
위의 작업을 수동으로 작성해보자.
## docker run = [ pull ] + create + start + [ command ]
## docker create는 docker run과 달리 Container에 프로세스를 올리지 않고, snapshot만 생성
root@hostos1:~# docker create -it --name myubuntu16-1 ubuntu:16.04
e0e60279cbd20a50b24f3a3d0333bfda23d33fcaef05b870fb9ce0594f92cdc9
## 상태가 Created인것을 확인할 수 있음
root@hostos1:~# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e0e60279cbd2 ubuntu:16.04 "/bin/bash" 4 seconds ago Created myubuntu16-1
## 생성된 스냅숏 동작시킴
root@hostos1:~# docker start myubuntu16-1
myubuntu16-1
root@hostos1:~# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e0e60279cbd2 ubuntu:16.04 "/bin/bash" 4 seconds ago Up 50 Seconds myubuntu16-1
## 컨테이너 접속
## docker attach는 실행 중인 애플리케이션 컨테이너에 단순한 조회 작업 수행 시 유용!
root@hostos1:~# docker attach myubuntu16-1
root@e0e60279cbd2:/#
-i : interactive ( 대화식 모드 열기 )
-t : tty( 단말 디바이스 할당 ) -it (작업수행)
-d : detach(백그라운드로 실행 -> nginx -> -d), 백그라운드 실행 후 컨테이너 ID 등록
-p : publish host_port:container_port, 호스트 포트와 컨테이너 포트 연결
-e : 환경변수 -> DB,
다수 환경 변수 사용 시 -> -e ... -e ... -e ... -> --env-file=env_list 파일에 환경변수 저장
--restart= : always | ... -> 사용자 stop이 아닌 예기치 않은 컨테이너 종료 시 자동 재시작, 기본값 = no
⁕ kubernetes는 기본값이 restart=Always로 되어 있음 -> auto-healing
--name : 컨테이너 이름
--rm : 컨테이너 stop과 동시에 자동 rm 수행 -> test용 container에 적합
-u : 컨테이너 기본 사용자는 root, 특정 계정에서 application 수행 시 -u=kevin
-w : workdir와 같이 컨테이너 내부 접속 시 연결되는 경로 지정
-v : 볼륨 지정(NFS와 유사, container to host, container to container)
log 체크
환경변수
container가 사용중인 자원 소비량을 측정한 결과 (data) -> metric -> cadvisor를 통해 모니터링
docker status nginx
kevin@hostos1:~$ docker events
되도록이면 exec를 사용하는 것이 좋다.
attach를 사용하면 세션이 같이 움직인다.
exec는 세션이 분리된다.
attach는 접근할 때 사용하는 것이 좋다.
## test Container의 /etc/passwd 파일을 Host의 /tmp/etc에 복사
kevin@hostos1:~$ docker run -itd --name=test_container centos
09d9db41168c7c14dc8e80634a65525a003b290058a9dc47a652d7ef06ef37db
kevin@hostos1:~$ docker cp test_container:/etc/passwd /home/kevin/centos_passwd.txt
kevin@hostos1:~$ touch local.txt
kevin@hostos1:~$ docker cp ./local.txt test_container:/tmp/local.txt
kevin@hostos1:~$ docker exec -it test_container ls /tmp
ks-script-4luisyla ks-script-o23i7rc2 ks-script-x6ei4wuu local.txt
kevin@hostos1:~$ docker run -d -p 7777:80 --name=webserver nginx:1.23.1-alpine
5f815b70318e4bb8dca24724dad7b8b99be770834e1cc0c5f30bbf960f905e2e
kevin@hostos1:~$ docker cp webserver:/etc/nginx/nginx.conf /home/kevin/nginx.conf
kevin@hostos1:~$ docker cp nginx.conf webserver:/etc/nginx/nginx.conf
컨테이너 내부에 있는 변동 사항을 출력해줌
[root@afb4db5919f2 /]# mkdir dir1
[root@afb4db5919f2 /]# touch file1
kevin@hostos1:~$ docker diff mycent2
A /dir1
A /file1
정리가 아주 잘 되어 있네요~👍👍