[Docker] 도커 이미지, 컨테이너 기본

728x90

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 버전을 변경하더라도 별도의 백업 작업 없이 간단하게 수정할 수 있다.

 

 

728x90