docker CLI 2편

#1. docker CLI :  run #1

##1. 준비 : 이미 존재하는 container를 모두 삭제하기.

$ docker ps -a --format '{{.ID}}' | xargs docker rm

 

##2.터미널을 2개를 실행한 뒤 각각 docker run을 해보자.

$ docker run -it --name ubuntu_top ubuntu "top" "-d 1"

other terminal
$ docker run -it --name ubuntu_top ubuntu "top" "-d 1"

터미널을 2개를 실행한 뒤 각각 docker run을 해보면 2번째 터미널에서 같은 명령을 실행 시 실패에러가 뜬다.

왜냐하면 동일한 NAME을 가진 container를 만들 수 없기 때문이다.

 

 

#2. docker CLI :  run #2

다른 이름을 가진 컨테이너의 경우

$ docker run -it --name ubuntu_top ubuntu "top" "-d 1"

other terminal
$ docker run -it --name ubuntu_top2 ubuntu "top" "-d 1"

PID 는 1이다. 왜냐하면 각 컨테이너 독립되기 때문이다.

 

#3. docker CLI :  run #3

하나의 컨테이너에서 2개 Top이 있게 하는 방법은?

1번 터미널의 ubuntu_top을 그대로 두고, 2번 터미널만 종료.

 

docker ps -a 로 확인해보면,

ubuntu_top2 는 꺼져있고, ubuntu_top은 실행 중이다.

 

#4. docker CLI :  exec #1      ( 실행 명령어 )

1. 하나의 컨테이너에 여러개 top을 실행하고 싶을 때 exec 사용 ( 여러개의 프로세스를 하나의 컨테이너에 넣기)

2. 2번째 터미널에서 exec 명령을 실행해보자.

top 을 쓰기에 terminal을 써야함에 따라 it 를 그리고 이미 존재하는 컨테이너에 붙어야기에  ubuntu_top을 사용

 

$ docker exec -it ubuntu_top top "-d 0.2"

/// 실행시키면 1번 터미널에서도 top 에 새로운 process가 보일 것이다.

#5. docker CLI :  exec #2      ( 실행 명령어 )

1. 3번째 터미널을 열고, exec 로 bash를 실행해보자.

$ docker exec -it ubuntu_top bash
# ps -ef

 

작동 연습을 다 했으면 컨테이너를 닫고, 삭제해두자. (PID 1번이 종료하면 container에 속한 프로세스들은 쫒겨난다.)

 

 

#6. docker CLI : binding

##1. container의 자원을 외부와 연결

1. 일반적으로 I/O와 storage관련을 연결한다.

  1) network

    가.  port binding :host OS의 port와 container의 port를 바인딩

    나. network :  docker network 사용  ( docker network를 만들어서 거기안에 포함시킴)

  2) directory, file, block-device   ( ** file: 보통 regular file 을 의미) 

     가. mount binding : host OS의 directory를 바인딩

     나. volume : docker volume 저장소 사용 ( docker compose와 같이 사용)

     다. device : host OS의 device, GPU를 바인딩

  3) environment

     가. shell environment variables를 지정. 

 

docker는 컨테이너로 컨테이너 안에 customizing 할 수 있는 설정이 있다. 이 설정을 미리 env1, env2... ( 환경변수)로 만든다.

환경변수에 어떤 값이 들어오면 docker는 특정 설정으로 작동한다.

도커 각 이미지 마다 이미지의 설명 페이지에 값 설정 조건이 기록되있으며 그에 따라,  env 값 설정을 바꾼다. 

 

#7 docker CLI : binding : net

** 포트번호:   http  80  , https   443 ,   ssh   22

 

1. nginx web server를 실행하기 위해..

  1) nginx container가 사용할 port를 config에서 확인해보자.

$ docker inspect nginx

 

80/tcp 포트를 외부에 노출하고 있음을 알 수 있다. 이 포트를 host OS의 포트에 바인딩시키면 외부 연결할 수 있다.

daemon 서비스는 Stdin/out/err  를 쓰지 않는다. SIGTTIN , SIGTTOUT을 발생시키지 않기 위함이다.

 

2)

1번 터미널 : nginx container 실행

2번 터미널 : 8080 포트 LISTEN확인

터미널 1
$ docker run --rm -p 8080:80/tcp --name nginx_8080 nginx


터미널 2
ss -nlt 'sport = :8080'   // == ss -nlt 'sport = 8080'

--rm : exits 할 때 컨테이너를 자동으로 제거.

-p 8080:80/tcp  : Bind port 8080 of all interfaces on the host to tcp port 80 on the container. 

 

-p : port를 binding.

8080 : host의 포트번호

80: container의 포트번호

시스템에 있는 8080포트로 들어오면 도커안에 있는 80포트와 연결해주겠다는 의미.

-nlt :  n  is numeric  ,  l is listen  , t is tcp

sport is source port     콜론 없어도 됨.

 

 

 

 

3)

2번 터미널에서 curl로 테스트해보자

$ curl 127.0.0.1:8080

127.0.0.1:8080 포트에 접속하면 nginx 페이지를 볼 수 있다.

물론 curl 대신 웹브라우저인 Firefox로도 볼 수 있다.

 

 

127.0.0.1  (내 ip) 대신 다른 특정 ip 입력 가능

 

 

4) 1번 터미널 : Stopping (CTRL-C)

exit되기에 자동으로 해당 프로세서는 삭제됨.

터미널 1
$ docker run --rm -p 8080:80/tcp --name nginx_8080 nginx


터미널 2
$ curl 127.0.0.1:8080

터미널2에서 8080으로 접속하면 첫번째 터미널1에서 172.17.0.1 - - [02/ ....  "-" 문구가 출력된다.

 

curl 로 웹서버에 접속하면 나오는 log는  stdout 으로 출력되고 있다.

그리고 container가 foreground로 작동하고 있기 때문에 해당 프로세스를 ^C 로 죽이면 docker가 닫히게 되고, --rm 옵션으로 인해 자동 삭제 된다.

foreground로 실행시키는 것은 너무 귀찮으니, background로 실행하고 싶다면?

 

#8 docker CLI : binding : net : detach

background에서 실행.

1. 1번 터미널 : detach mode  

-d : detach

$ docker ps -a
$ docker run -d --rm -p 8080:80/tcp --name nginx_8080 nginx
$ docker ps

2. 2번 터미널 : logs (following mode를 사용하려면 -f옵션 사용)

다른 창에서 로그 확인 가능.

$ docker logs-f nginx_8080  // $ docker logs -f nginx_8080

 

출력물.

fe6a55...b0  : container id 이름

docker ps 에선 잘라서 나옴. fe6a55bf5로.

Up :작동 중.

 

 

#9 docker CLI : attach, detach

##1. docker run -it ...

 1. interactive mode & terminal 을 사용하는 경우.

  1) container를 running 상태로 두고 잠시 빠져나올 때는 detach를 할  수 있다. 

     가. escape key sequence : ^P^Q    **^ is ctrl.

  2)  처음 실행 할 때 -d 옵션을 추가하면 detach mode 로 실행할 수 있다.

$ docker run --rm -itd --name ubuntu_bash ubuntu bash
$ docker attach ubuntu_bash
# ps

^P^Q 누르면 'read escape sequence' 가 출력되며 host로 나올 수 있다.
다시 attach한 뒤에 exit로 나오면 container가 종료되면서 rm된다

 

 

** tmux 란?

 

#10 docker CLI : binding : mount #1

##1 nginx에 외부 디렉터리를 mount 해볼텐데, 그전에 할 일이 있다.

1. nginx 웹서버가 사용하는 디렉터리 구조 알기.

  1) https://hub.docker.com/_/nginx   에 문서가 잘 정리되어 있어 공식 문서를 잘 활용해야한다.

  2) 하지만, 설정 파일 내용은

   직접 컨테이너에 들어가보는게 빠르다.

    물론 웹서버 구조는 알아야한다.

#11 docker CLI : binding : mount #2

1번 터미널 : nginx docker container 내부로 들어가보자.

 1. 아래 bash 실행 목적은 슬쩍 보기 위함(실제 서비스 용도가 아님)

 

$ docker run --rm -it nginx bash
# alias ls='ls --color'
# cd /etc/nginx
# ls
# cd conf.d
# ls
# more default.conf

#12 docker CLI : binding : mount #3

config파일에서 root가 /usr/share/nginx/html임을 확인했으니 exit하자.

server {
    listen       80;
    server_name  localhost;

    #access_log  /var/log/nginx/host.access.log  main;

    location / {    ##  '/' is root
        root   /usr/share/nginx/html;   ##  /usr/share/nginx/html이 바로 web document root임. 여기를 외부 host에서 mount로 binding 해보자.
        index  index.html index.htm;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

 

**ls를 aliasing 해서 색상이 이쁘게 나오게 설정.

 

 

exit 한 후 bash 작업을 나가고 host운영체제로 돌아온다.

 

#13 docker CLI : binding : mount #4

##1. 1번 터미널 : container에 binding할 dir의 준비 및 실행.

 1)  binding directory : $HOME/nginx_doc_root  [HOST 운영체제] ==> /usr/share/nginx/html     [Container의 디렉터리]

**개인용이니 자신의 유저의 홈 디렉터리에 만든 것이다.

 

$ mkdir ~/nginx_doc_root/
$ readlink -f ~/nginx_doc_root
$ echo "Hello Document root dir" > ~/nginx_doc_root/hello.txt
$ ls ~/nginx_doc_root/

## -v host_file:container_file  host_file을 container_file에 바인딩.  예시에는 1개지만 여러 volume을 지정할 수 있음.
$ docker run --rm -d -p 8080:80/tcp \
> -v /home/jlim/nginx_doc_root:/usr/share/nginx/html \
> --name nginx_8080 nginx

기존에 nginx 가 실행되서 에러가 난 부분을 해결하고자 이전에 실행 한 nginx 를 중지하고 $ docker stop nginx  

해당 nginx를 삭제해준다. 그리고 다시 명령어를 입력했다.

 

이제 테스트를 해보자.

#14 docker CLI : binding : mount #5

##1. 2번 터미널 : curl로 nginx에 접속해보자.

$ curl 127.0.0.1:8080
$ curl http://127.0.0.1:8080/hello.txt
$ echo "Hello world" >> ~/nginx_doc_root/hello.txt
$ curl http://127.0.0.1:8080/hello.txt   ## 바인딩된 곳의 file을 변경하면 당연히 변경점이 반영된다. 둘은 같은 파일이기에.
$ docker stop nginx_8080   ## stop을 통해 해당 컨테이너를 중지시킨다. 컨테이너 중지 시 --rm 옵션 사용했으니 자동삭제가 이루어짐.

 

#15 docker CLI : binding : mount #6

##1. -v (--volume) 대신 --mount 사용방법.

$ docker run --rm -d -p 8080:80/tcp \
--mount type=bind,src=/home/jlim/nginx_doc_root,dst=/usr/share/nginx/html \
--name nginx_8080 nginx

1. type=bind : mount의 bind 기능.

2. type=volume : volume을 사용

 

volum 사용은 docker volume 명령어에서 살펴 볼 수 있다.

** docker에서는 -v 보다 --mount를 더 권장하고 있다. 명령어의 직관, 통일성

 

#16 docker CLI : binding : Env

##1. environment variables

1. --env KEY=value

2. --env-file env_file

  1) This file should use the syntax <variable>=value

 

eg.

$ docker run --rm -it --name ubuntu_bash ubuntu bash
# echo $LANG
# exit
$ docker run --rm -it -e LANG=en_US.utf8 --name ubuntu_bash ubuntu bash
# echo $LANG
# exit

 

#17 docker CLI : volume, net

##1. docker volume, network

 1. docker volume

  1) docker volume management

     가. Logical volume과  흡사.

  2) docker network

     나. network IP address, subnet mask 등 설정 

 

** 이 기능들은 docker-compose 와 같이 쓰이는 경우가 많다. 개별적으로 쓰기에는 관리가 복잡하기 때문.

 

#18 docker CLI : stop, start

##1. docker stop, start는 어떤 경우에 사용하나?

1. docker stop

 1) detached mode로 실행중이라면, 외부에서 docker stop으로 정지

 2) -it를 사용하지 않는 시스템은 signal 혹은 docker stop으로 정지.

 

2. docker start

 1) docker run --rm 을  쓰지 않는 경우 exited시 container는 남는다.

 2) stop 후 재시작할 때는 start로 가능

 

Practice : docker stop, start

예시 : detached mode로 작동시킨 nginx를 stop, start.

$ docker run -d -p 8080:80/tcp \
> --mount type=bind,src=/home/jlim/nginx_doc_root,dst=/usr/share/nginx/html \
> --name nginx_8080 nginx

$ docker ps

$ docker stop nginx_8080 && docker ps -a

$ docker start nginx_8080 && docker ps

 

Summary

1. docker run의 선택적 옵션

  1) detach mode : -d

  2) stdio의 사용 : -it   ## -it --> ^P^Q   --> attach

  3)종료시 제거 : --rm

  4) binding (port) : -p host_port:container_port

  5) binding (file) : --mount .... or  -v ....   # --mount를 권장

  6) binding (env.) : -e KEY=value or --env-file ...   ## file을 만들어 .. 에 넣기.

 

+ Recent posts