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을 만들어 .. 에 넣기.
'프로그래머스 > Docker' 카테고리의 다른 글
| vs code 에서 도커 연결하기 (0) | 2023.01.30 |
|---|---|
| [인공지능 개요] Docker #5 - docker-compose (0) | 2023.01.03 |
| [인공지능 개요] Docker #3 - CLI -ps rm rmi image (0) | 2023.01.02 |
| [인공지능 개요] Doker #2 - installation (0) | 2023.01.02 |
| [인공지능 개요] Doker #1 - history chroot container (0) | 2023.01.02 |