docker 명령 구조
$ docker container <sub-command>
$ docker image <sub-command>
$ docker network <sub-command>
$ docker volume <sub-command>
이미지 관련 명령어
로컬 도커 이미지 목록 확인
$ docker images
도커 이미지 검색
$ docker search <이미지_네임>
도커 이미지 다운로드
$ docker pull <이미지_네임:태그>
도커 이미지 다이제스트로 다운로드
$ docker pull <이미지_네임@sha256:digest_string>
choi@localhost ~ docker pull centos@sha256:8faead07bd1d5fdd17414a1759eae004da5daa9575a846f4730f44dec0f47843
docker.io/library/centos@sha256:8faead07bd1d5fdd17414a1759eae004da5daa9575a846f4730f44dec0f47843: Pulling from library/centos
ce510b3e7858: Pull complete
Digest: sha256:8faead07bd1d5fdd17414a1759eae004da5daa9575a846f4730f44dec0f47843
Status: Downloaded newer image for centos@sha256:8faead07bd1d5fdd17414a1759eae004da5daa9575a846f4730f44dec0f47843
docker.io/library/centos@sha256:8faead07bd1d5fdd17414a1759eae004da5daa9575a846f4730f44dec0f47843
이미지 버전 문제 때문에 다이제스트 값을 사용하여 이미지를 풀링한다.
이미지 삭제
$ docker rmi <이미지_네임>
inspect
$ docker inspect <이미지_ID>
$ docker inspect <이미지_이름>
$ docker inspect centos:7 --format '{{ .Config.Cmd }}'
유의깊게 볼 것은 ContainerConfig 와 Config 부분이다.
ContainerConfig 는 이 이미지를 최초로 생성했을 때 사용했던 설정들이 담겨있다.
Config 는 가장 최근에 이미지를 생성했을 때 사용했던 설정들이 담겨있다.
- Config 에서 유의 깊게 볼 것들
- Env : 환경 변수
- Cmd
- ExposedPorts
- WorkingDir : 어플리케이션이 실행될 경로
- Volumes
- Entrypoint
이미지 저장/아카이브
$ docker save <이미지_이름> -o <파일_이름>
choi@localhost ~ docker save centos:7 -o centos:7.tar
choi@localhost ~ file centos:7.tar
centos:7.tar: POSIX tar archive
tar 파일을 압축 풀면 layer.tar 파일이 존재하고 해당 파일안에 실제 동작하는 파일들이 들어가 있다.
이미지 가져오기
$ docker load -i <파일_이름>
choi@localhost ~ docker load -i centos7.tar
4859ae5ec3f3: Loading layer 211.3MB/211.3MB
Loaded image ID: sha256:d0be79ecaa51a8dd0d144ac7084e8407d06185aa81c214fb12fdd0ad7b5d3ad1
컨테이너
현재 실행 중인 컨테이너 목록
$ docker ps
모든 컨테이너 목록
$ docker ps -a
컨테이너 실행
$ docker run <이미지_이름>
$ docker run --name <이미지_이름>
동일한 이름의 컨테이너는 생성되지 않는다.
docker run 명령어 옵션
choi@localhost ~ watch -n 5 -d docker ps -a
Every 5.0s: docker ps -a localhost: Wed May 4 02:20:20 2022
CONTAINER ID IMAGE COMMAND CREATED
STATUS PORTS NAMES
ab0a1cbb3f4f mysql:5.7 "docker-entrypoint.s…" 38 seconds a
go Exited (1) 37 seconds ago upbeat_lichte
rman
50b11d1d5b41 httpd "httpd-foreground" About a minu
te ago Exited (0) About a minute ago optimistic_gr
othendieck
- 옵션 없음 : Docker Daemon 이 stdout,stderr 을 Docker Client 에게 전달한다.
- -it: Attach 모드. stdin, stdout, stderr 을 내 터미널에 연결해준다. → Foreground 실행
- -i : stdin 유지
- -t: Terminal 할당
- ctrl-p-q 를 눌러서 실제 컨테이너를 종료하지 않고 빠져 나올 수 있다.
- ctrl-p-q 빠져나온 후 다시 쉘로 들어가고 싶을 경우 docker attach 컨테이너_이름 으로 다시 들어갈 수 있다.
- -d: Detach 모드. stdin, stdout, stderr 를 떼어낸다. → Background 실행
하나의 컨테이너는 하나의 애플리케이션만 실행한다.
-itd 로 실행할지 -it 로 실행할지 -d 로 실행할지 잘 정해야 한다.
docker restart 정책
$ docker run --restart <no|always|on-failure|unless-stopped> <IMAGE>
docker pull 정책
$ docker run --pull <missing|always|never> <IMAGE>
docker 프로세스 목록 확인
$ docker top <컨테이너_이름>
docker exec
기본 컨테이너를 띄운 후에 추가적으로 애플리케이션을 실행할 수 있도록 해준다.
$ docker run -d httpd
$ docker run -it <httpd_컨테이너_아이디> bash
$ docker top <httpd_컨테이너_아이디>
Every 1.0s: docker top e8 localhost: Wed May 4 05:15:41 2022
UID PID PPID C
STIME TTY TIME CMD
root 27716 22819 0
05:15 pts/0 00:00:00 bash
위처럼 httpd 에서 bash 만 실행되는 것을 확인할 수 있다.
$ docker run -d httpd
$ docker exec -it <httpd_컨테이너_아이디> bash
$ docker top <httpd_컨테이너_아이디>
Every 1.0s: docker top e8 localhost: Wed May 4 05:15:41 2022
UID PID PPID C
STIME TTY TIME CMD
root 22839 22819 0
05:09 ? 00:00:00 httpd -DFOREGROUND
www-data 22870 22839 0
05:09 ? 00:00:00 httpd -DFOREGROUND
www-data 22871 22839 0
05:09 ? 00:00:00 httpd -DFOREGROUND
www-data 22872 22839 0
05:09 ? 00:00:00 httpd -DFOREGROUND
root 27716 22819 0
05:15 pts/0 00:00:00 bash
주로 컨테이너에 띄워진 애플리케이션을 테스트하고 관리할 때 exec 를 사용한다.
docker stats
컨테이너의 리소스 사용량을 확인할 수 있다. 기본적으로 초 단위로 계속해서 보여준다.
--no-stream 은 딱 한 번만 표기해준다.
choi@localhost ~ docker stats --no-stream
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
ec7fac1095d4 inspiring_kalam 0.01% 6.051MiB / 3.817GiB 0.15% 3.77kB / 0B 0B / 4.1kB 82
--cpus 옵션(cpu 리소스 제한)
컨테이너는 하드웨어 리소스 양 제한이 걸려 있지 않다. 그래서 필요한만큼 하드웨어 리소스를 사용할 수 있다.
그래서 run 명령 시에 cpu 리소스 제한을 걸 수 있다.
$ docker run --cpus 0.1 <이미지_이름 또는 ID>
--memory 옵션(메모리 리소스 제한)
메모리 리소스 제한
$ docker run --memory 100m <이미지_이름 또는 ID>
choi@localhost ~ docker run -d --cpus 0.1 --memory 100m ubuntu sha512sum /dev/zero
e5de251f8aae529c51e72c654074582ad8eddd9c39265602fe59b56fce0388b2
choi@localhost ~ docker stats --no-stream
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
e5de251f8aae elastic_elgamal 10.15% 372KiB / 100MiB 0.36% 2.34kB / 0B 0B / 0B 1
1a27b47f78fb cool_turing 9.86% 1.527MiB / 3.817GiB 0.04% 3.41kB / 0B 0B / 0B 3
docker update
컨테이너 리소스 제한 변경
$ docker update --cpus 0.2 --memory 200m <컨테이너_이름 또는 ID>
컨테이너는 라이프 사이클이 매우 짧은 편에 속한다.
그래서 컨테이너 내부에 로그를 기록하지 않는다. 실제 로그는 도커 호스트에 기록된다.
choi@localhost ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9d5d9f83b041 httpd "httpd-foreground" 8 minutes ago Up 8 minutes 80/tcp dazzling_johnson
choi@localhost ~ sudo -i
root@localhost:~# cd /var/lib/docker/containers/9d5d9f83b0417b5fbf4409e934e8511f5a18ba40f6581443fa19277bd82ac2e1/
root@localhost:/var/lib/docker/containers/9d5d9f83b0417b5fbf4409e934e8511f5a18ba40f6581443fa19277bd82ac2e1# cat 9d5d9f83b0417b5fbf4409e934e8511f5a18ba40f6581443fa19277bd82ac2e1-json.log
{"log":"AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message\\n","stream":"stderr","time":"2022-05-04T06:14:57.114936204Z"}
{"log":"AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message\\n","stream":"stderr","time":"2022-05-04T06:14:57.115974327Z"}
{"log":"[Wed May 04 06:14:57.116577 2022] [mpm_event:notice] [pid 1:tid 281473787777040] AH00489: Apache/2.4.53 (Unix) configured -- resuming normal operations\\n","stream":"stderr","time":"2022-05-04T06:14:57.116871576Z"}
{"log":"[Wed May 04 06:14:57.116700 2022] [core:notice] [pid 1:tid 281473787777040] AH00094: Command line: 'httpd -D FOREGROUND'\\n","stream":"stderr","time":"2022-05-04T06:14:57.116879076Z"}
위 예제처럼 실제 로그 파일은 root 에서 /var/lib/docker/container/컨테이너_아이디/컨테이너_아이디-json.log 에 컨테이너 로그를 확인할 수 있다.
docker 호스트에서 로그(stdout/stderr)를 보기 위해서는 docker logs 컨테이너_아이디 를 입력하면 된다.
그러면 로그는 위 디렉토리에서 로그 파일을 읽어들인다.
문제는 컨테이너를 삭제하면 해당 컨테이너의 로그가 사라지게 된다. 로그는 무조건 남겨야 한다.
syslog 서버를 만들어서 컨테이너의 모든 로그를 syslog 로 보내는 방법을 사용하면 된다. 하지만 이 방식은 거의 사용하지 않는 방식이다.
아마존의 CloudWatch 에 로그를 남기는 방식도 있다.
위의 방식들은 순수하게 도커만 사용하는 경우에 사용한다. 쿠버네티스를 사용할 경우에는 위 방식들을 사용할 필요가 없다.
중점은 컨테이너를 삭제하면 로그가 삭제되기 때문에 로그를 외부 서버나 서비스에 남겨야 한다는 것이다.
환경 변수
$ docker run -e A=100 ubuntu
$ docker run -d -e MY_SQL_ROOT_PASSWORD=password mysql:5.7
컨테이너 IP 확인
$ docker inspect 컨테이너_아이디 -f '{{ .NetworkSettings.IPAddress }}'
컨테이너 DIscovery
$ docker run --name mysqldb -d -e MYSQL_ROOT_PASSWORD=1234 myslq:5.7
$ docker run -it --link mysqldb ubuntu bash
> cat /etc/hosts
>> 172.17.x.x mysqldb
$ docker run -it --link myslqdb:db ubuntu bash
> cat /etc/hosts
>> 172.17.x.x mysqldb ab
$ docker run -it --link mysqldb:db mysql:5.7 mysql -h db -u root -p
컨테이너의 포트를 호소트의 포트로 포워딩(포트 포워딩)
$ docker run -p host_port:container_port 이미지_이름
$ docker run -d -p 80:80 httpd
docker 로 워드프레스 띄워보기
$ docker run --platform linux/amd64 -d \
--name wordpressdb --restart always \
-v /tmp/docker/wordpress_db:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=1234 \
-e MYSQL_DATABASE=wordpress mysql:5.7
$ docker run --platform linux/amd64 -d \
--name wordpress --link wordpressdb:mysql \
-p 80:80 -e WORDPRESS_DB_PASSWORD=1234 \
-e WORDPRESS_DB_DATABASE=wordpress \
-e WORDPRESS_DB_USER=root \
-e WORDPRESS_DB_HOST=mysql \
wordpress:5.9.3-apache
$ curl ifconfig.me # 이 아이피로 접속을 하면 워드프레스 설치 화면이 나온다.
MAC 에서 docker 를 실행하면 바로 docker 를 실행하는 것이 아니라 VM 을 띄우고 그 위에 도커를 실행시키기 때문에 /var/lib/docker 디렉토리가 존재하지 않는다. 그래서 docker run 할 때 -v 옵션으로 볼륨을 마운트하여 사용한다.
그래서 mysql 을 실행할 때 -v /tmp/docker/wordpress_db:/var/lib/mysql 옵션을 줘서 마운트하여 사용했다. 즉, 컨테이너에서 저장하는 데이터를 호스트의 /tmp/docker/wordpress_db/ 에 저장한다는 뜻이다.
이렇게 하면 mysql 컨테이너를 제거해도 워드프레스에서 사용하는 데이터들은 호스트에 남아있기 때문에 안전하고 mysql 버전을 변경하더라도 별도의 백업 작업 없이 간단하게 수정할 수 있다.