20220504 필기노트

강재민·2022년 5월 4일
0

필기노트

목록 보기
2/23

이전 수업 내용 보충

Lifecycle에서..
실행중인 컨테이너는 rm명령어로 삭제할 수 없다.


수업내용 요약


Docker 관리

최신 docker 명령 구조

docker container <sub-command>
docker image <sub-command>
docker network <sub-command>
docker volume <sub-command>

이미지

로컬 이미지 목록 확인

docker images

Docker Hub 이미지 검색

docker search <TERM>

이미지 풀링

docker pull <IMAGE>:<TAG>
docker pull <IMAGE>@<HASH>

이미지 삭제

docker rmi <IMAGE>

이미지 상세정보 확인

docker inspect <IMAGE>

ContainerConfig vs Config

  • ContainerConfig: 이미지 최초 생성할 때 사용했던 설정

  • Config: 가장 최근에 이미지 생성시 사용했던 설정

  • Config
    - Env
    - Cmd
    - ExposedPorts
    - WorkingDir
    - Volume
    - Entrypoint
    - Volumes

docker inspect centos:7 --format '{{ .Config.Cmd }}'

이미지 저장/아카이브

docker save <IMAGE> -o <FILE>

이미지 가져오기

docker load -i <FILE>

컨테이너

create -> start -> (pause) -> (unpause) -> (kill) -> (restart) -> stop -> rm
run ---------->

컨테이너 목록

현재 실행중인 컨테이너 목록

docker ps

모든 컨테이너 목록

docker ps -a

컨테이너 실행

docker run <IMAGE>
docker run --name <IMAGE>

동일한 이름의 컨테이너 생성 X

  • 옵션 없음: Docker Daemon --stdout/stderr-> Docker Clinet
    - --name 옵션 X
  • -it: Attach 모드(stdin/stdout/stderr 연결) -> Foreground
    - -i: stdin 유지
    - -t: Terminal 할당
    - ctrl-p-q
    - docker attach 명령으로 연결 가능
  • -d: Detach 모드(stdin/stdout/stderr 연결 해제) -> Background 실행
  • -itd

하나의 컨테이너에는 하나의 Application만 실행 원칙

재시작 정책

https://docs.docker.com/config/containers/start-containers-automatically/

docker run --restart <no|always|on-failure|unless-stopped> <IMAGE>

이미지 풀 정책

docker run --pull <missing|always|never> <IMAGE>

컨테이너의 프로세스 목록 확인

docker top <CONTAINER>

실행중인 컨테이너만 확인

컨테이너에서 (추가)애플리케이션 실행

docker exec <CONTAINER> <COMMAND>
docker exec -it a8 bash
docker exec a8 cat /etc/httpd/conf/httpd.conf

컨테이너 리소스 사용량 확인

docker stats
docker stats --no-stream

컨테이너 (cpu/memory) 리소스 제한

docker run --cpus 0.1 --memory 100m ubuntu sha256sum /dev/zero

컨테이너 리소스 제한 변경

docker update --cpus 0.2 da
docker update --memory 200m da

컨테이너 로그(stdout/stderr) 확인

/var/lib/docker/container/<ID>/<ID>-json.log
docker logs <CONTAINER>

컨테이너를 삭제하면 로그도 삭제됨

환경변수

docker run -e A=100 ubuntu
docker run -d -e MYSQL_ROOT_PASSWORD=P@ssw0rd -e MYSQL_DATABASE=wordpress mysql:5.7

일부 이미지는 실행시 환경 변수가 필요함

컨테이너 정보 확인

docker inspect <CONTAINER>

컨테이너 IP 확인

docker inspect 16a -f '{{ .NetworkSettings.IPAddress }}'

컨테이너 Discovery

docker run --name mysqldb -d -e MYSQL_ROOT_PASSWORD=P@ssw0rd mysql:5.7 
docker run -it --link mysqldb ubuntu bash

> cat /etc/hosts
>> 172.17.X.X mysqldb
docker run -it --link mysqldb:xyz ubuntu bash

> cat /etc/hosts
>> 172.17.X.X mysqldb xyz
docker run -it --link mysqldb:xyz mysql:5.7 mysql -h xyz -u root -p

컨테이너의 포트를 호스트의 포트로 포워딩 (포트 포워딩)

docker run -p <HOST>:<CONTAINER> <IMAGE>
docker run -d -p 80:80 httpd

필기내용 시작


이미지

docker images #로컬 이미지 목록 확인
docker image [tap][tap]
docker image ls
docker images


이런 명령어외에는 거의 사용하지 않을 예정
나중에 나온 명령어들이고


이것들은 도커 초창기 버전부터 사용되었던 명령어로 모두 중요한 명령어들임

docker container [tap] [tap]

컨테이너를 관리하는 명령어들을 확인할 수 있다.


최신 docker 명령 구조

docker container <sub-command>
docker image <sub-command>
docker network <sub-command>
docker volume <sub-command>
docker search
docker search ubuntu


자동화이미지생성은 비트코인 채굴하는데 너무 많이써서 유료로 막아놓음

이렇게 도커 홈페이지에서 검색했듯이 리눅스환경에서도 이미지 검색이 가능하다.

docker pull centos

하면 이미지만 받아옴 그 중에서도 태그는 지정하지 않았기 때문에 latest 이미지를 받아옴


DIGEST 값이 같으면 같은 이미지임 다르면 다른 이미지임 그리고
2108이러면 21년 08월에 배포한 이미지라는 뜻임



이렇게 이름은 달라도 같은 이미지라서 이미지 설치도 거의 안하다싶이 끝난다



이미지는 같고 태그가 여러 개 이기 때문에 rm하면 태그만 제거되고 이후에 나머지 이미지까지 지우면 저장된 이미지의 내용이 모두 지워진다


이미지 버전관리

지금은 같은 이미지로 태그만 다르지만 앞으로도 이게 계속 같은 이미지일까에 대한 생각을 해보자

centos7은 오피셜 이미지라서 최신 버전을 의미하고 새로운 버전이 나오면 나중에 달라질 수 있다. 그래서 버전을 지정해주고 만드는게 기본이다.

잘되는건 앵간하면 바꾸지않는다 -장성균강사님

버전을 지정해주어도 혹시나 실수로 이미지를 변경할 수도 있는데 이를 방지하기위해서.. 근데 공부해보다보니 실행할 때 새로운 버전을 계속 설치하는 옵션을 지정안해주면 그럴일 없어보이던데..
이미지 태그를 눌러보면 DIGEST에 값이 쭉 나온다.

docker pull centos@[DIGEST값]

hash는 이미지의 내용을 가지고 만드는 것이기 때문에 버전이 바뀌더라도 DIGEST값은 바뀌지 않으므로 이 방식이 가장 안전하다고 할 수 있다.

이미지삭제는

docker rmi <IMAGE>

이미지 상세정보 확인

docker container inspect
docker volume inspect
docker network inspect
docker inspect centos:7 #예를들어

이런 명령어들이 있다.


질문) CVE는 무엇입니까?


이미지 취약점이 감지가 되었는지에 대한 내용

CVE의 개념을 짚고 넘어가보자
https://www.mitre.org/
MITRE라는 회사가 있는데 비영리단체이고 국방, IT관련 취약점, 해킹에 대해 조사하고 연구하는 기관이다.
이 회사가 전세계 거의 표준이라고 할 수 있다.
Commen Vulerabilities and Ecposures의 약자임
https://cve.mitre.org/
https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=log4j
소프트웨어 업데이트할 때 이런 내용들을 보게 될 수 있음


docker inspect [이미지이름]

docker inspect ubuntu

ContainterConfig
Config
라는 내용이 있는데

ContainterConfig이미지를 최초 생성할 때 사용했던 설정
Config가장 최근에 이미지 생성시 사용했던 설정, 이게 실제로 적용될 내용임
이미지이기 때문에 Hostname은 설정할 수 없음
CMD는 실행할 어필리케이션
Env는 환경변수
Image는 해쉬값
Label은 일종의 주석이다.
  • Config
    - Env
    - Cmd
    - ExposedPorts
    - WorkingDir
    - Volume
    - Entrypoint
    - Volumes

실습

docker image pull mysql:5.7
docker inspect mysql 			#하면 뜨지않음
docker inspect mysql:5.7


이부분에 신경써서 공부할 것임



rc라고 되어있는 부분은 release candidate라고해서 배포 후보이다.
버전을 출시하기 전에 문제가 없으면 출시 예정인 이미지라고 볼 수 있다.


docker image pull mariadb:10.7
docker inspect mariadb:10.7

지금까지 매번 이렇게 json으로 보았는데

이렇게하면 원하는 부분만 볼 수 있다.
최상위에 있는 .Config.Cmd 이렇게 표현되어있는것임
대소문자 구분함

결과값

이렇게 해서 docker inspect centos:7 --format '{{ .Config.Cmd }}' 볼 수 있다


이미지 저장/아카이브

이미지안의 내용이 궁금할 때 어떻게 볼 지에 대해서 알아보려고한다.

save를 쓰면 이미지를 file로 다시 저장할 수 있다.

docker save hello-world -o hello-world.tar
file hello-world.tar
mkdir hello-world
tar xf hello-world.tar -C hello-world
cd hello-world
ls
tar xf layer.tar
ls
file hello
./hello 		#해보면 아까 실행했던 내용이 그대로 실행됨
cd ..
rm -rf hello-world

레이어란?


이런게 레이어임

docker image save centos:7 -o centos7.tar
mkdir centos7
tar xf centos7.tar -C centos7
cd centos7
ls
cd c5..
ls
tar xf layer.tar
ls 						#이 내용들이 다 바이너리나 라이브러리들임

docker save mysql:5.7 -o mysql5.7.tar
mkdir mysql
tar xf mysql5.7.tar -C mysql
cd mysql
ls
cd 2727...
ls
tar xf layer.tar
ls
sudo apt install tree
tree

이런식으로 save해서 이미지 내용을 확인할 수 있다고한다


이미지 가져오기

docker rmi centos:7
docker load
docker load --help
docker load -i centos7.tar
docker images

load는 이미지를 가져오는거
누군가가 이미지를 만들어서 tar 아카이브를 해서 보내주면 load로 받아는거긴한데 요즘은 레지스트리로 바로 네트워크에서 받아오면 되는거라 많이 쓰지는 않는 기능임


지금까지 이런 명령어들을 살펴보았다고 한다.


컨테이너


이렇게 연동되서 컨테이너 정보를 표기하는 것이다

docker run --name hello hello-world

하면 컨테이너 이름을 지정할 수 있다.
다만 이렇게하다보면 이름이 겹칠 수가 있어서 그냥 이름은 자동으로 생성하는 편이다.

컨테이너 명령어의미
옵션없음Docker Daemon --stdout/stderr ->Docker Client
-it-i는 stdin유지 -t는 Terminal 할당 (이걸 일종의 Attach모드라고도 한다)
-dDetach 모드(stdin/stdout/stderr 연결 해제) -> Background 실행

옵션없이 컨테이너 실행

docker run httpd

하면 나오는 항목들은 appach의 표준 출력 및 표준 오류이다

watch ls 					#기본 2초마다 ls를 실행시켜주고 그 결과를 보여준다
watch docker ps -a
watch -n 1 docker ps -a		 #-n은 동기화해주는 텀임
watch -n 0.5 docker ps -a
watch -n 5 -d docker ps -a	 #-d는 달라진부분을 하이라이팅해줌

이렇게 실시간으로 명렁어를 볼 수 있다.

이런식으로 실행되는것은 포트가 열려있는것도 확인할 수 있다.

docker ps -aq 				# q는 quiet명령어임
docker rm `docker ps -aq`	# 모두 제거

너무 컨테이너들이 많으면 이런식으로 작업할 수도 있긴한데 실제로는 이렇게 하면 안됨


-it옵션으로 컨테이너 실행

docker run -it ubuntu
ctrl pq 				#하면 여전히 실행되는 상태에서 빠져나올 수 있다
docker attach [container이름] # 하면 다시 접속할 수 있다. (단 조건은 -it옵션으로 실행한 것만 할 수 있다. 붙인다는 것은 stdinput을 붙인다는 말임)

-d 옵션으로 컨테이너 실행

docker run -d httpd

이렇게 실행을 하고 나중에 로그의 형태로 오류같은 것들을 확인하는 과정을 거칠 예정

docker attach [컨테이너 이름]
또는
docker attach [컨테이너 ID]

하면 실행이 안됨
왜냐하면 이건 표준 입력을 받아야하는데 우리는 시그널을 사용하는거기때문
ctrl+c라는것은 시그널이고 시그널은 입력이 아니다

docker run -itd httpd
docker attach 86
ctrl+pq					 #빠져나오는 명령어
docker run -itd ubuntu
docker attach 37
ctrl+pq					 #빠져나오는 명령어

강제로 컨테이너 삭제


본래 목적과 다른 실행을 시킨 경우

docker run -itd httpd bash

또는

docker run -it httpd bash

이렇게 실행하는 이유는 디버깅을 하거나 조치를 취해야 하는 경우 사용하긴하는데 이렇게 쓸일은 거의 없다


경로 호출

docker inspect httpd -f '{{ .Config.WorkingDir }}'


말그대로 어플리케이션이 실행될 경로
그래서 각자 bash 했을 때 경로가 달랐던것임

antipattern
기본적으로 하나의 컨테이너는 하나의 어플리케이션을 실행하는 것이 기본원칙이다.
다만 어플리케이션을 묶어서 사용할 수 도 있긴하다


명령어는 환경변수 어딘가에는 존재해야한다는 것

docker run ubuntu echo "hello world"
docker run ubuntu ls

응용 사례


ctrl+pq로 빠져나왔다가 다시 attach로 들어가는 형태가 가능


안좋은 응용사례


bash바이너리가 없어서 의미없는 옵션이 되었다


실행은 되었지만 출력을 볼 수 는 없을뿐임


질문) Binary란?

물론 이진수라는 뜻은 알고 있었지만 정확히 이진수라는 의미로만 쓰이는것 같지는 않다 그래서 질문함
실행파일을 의미한다고 한다 생각보다 별거 없었던.. 근데 그냥 실행파일이라고 하면되지 꼭 바이너리라고 함


몇가지 더 있는 옵션


-P --restart 보면 기본적으로 종료가 되면 재시작되지 않는것이 기본값으로 설정되어있다.
https://docs.docker.com/config/containers/start-containers-automatically/
여기에 보면

다양한 옵션이 있고 always옵션은 말 그대로 항상 재시작한다는 의미이다.

docker run -it --restart always ubuntu


항상 재시작한다는 의미

docker stop 61

해서 의도적으로 중지를 시킬 수 있음

unless-stopped 도커가 재시작될때 굳이 실행안하겠다는거
on-failure에러에 대해서 몇번에걸쳐서 재시작하는거

도커 명령어를 스트림할 공간이 없어서 더이상 실행이 되어도 한 번만 실행되고 더이상 출력되지 않는다.
docker run --restart always hello-world


always는 항상 받는다는것
never는 없으면 굳이 받아오지 않겠다는것

docker run --pull always hello-world
docker run --pull never hello-world

기본값은 missing이라는점 알아두고 missing은 존재하면 굳이 업데이트를 안하기 때문에
로컬에있는것만 이미지를 불러오기 위해서는 never옵션을 사용해야한다.


docker run -d httpd
docker ps
docker top fc(이건 컨테이너 이름) #현재 컨테이너 내에 실행되고있는 프로세스의 목록을 볼 수있다

프로세스가 여러개인것도 같은 어플리케이션으로 취급해서 꼭 하나의 컨테이너에 하나의 프로세스가 있어야하는것은 아니다


docker exec

docker run -d httpd
docker ps

컨테이너 내부로 진입해서 무언가를 바꾸려고 한다면
docker run -it httpd bash 같은 경우에는 bashshell만 떠있기 때문에 무언가 작업을 할 수가 없음

exec는 기존에 컨테이너에서 추가적인 어플리케이션을 실행할 수 있음

docker exec a8 hostname
docker exec -it a8 bash


이렇게 bash를 썻다가 나올 수 있음

그렇다고해서 docker attach a8로 다시 접속할 수 는 없음
이제 Ctrl+c하면 종료가 됨


그리고 당연히 vi에디팅은 할 수 없다. 그래서 cat명령어를 통해서 파일을 만들거나 sed를 이용해서 수정을 한다


이렇게 작게 사이즈를 유지하기 위해서는 웬만하면 exec를 이용하기위해 이미지 크기를 키우는것은 추천하지않는다


컨테이너에서의 프로세스 개념


이 차이를 알아야함


리눅스에서 바라볼 때는 컨테이너든 다른것이든 모든 프로세스를 볼 수있지만 도커엔진에서는 Namespace를 이용했기 때문에 다른 곳에 있는 프로세스는 볼 수 없다


컨테이너의 리소스 활용 우수성


컨테이너를 사용하는 장점 성능을 100% 뽑아낼 수있음


컨테이너와 가상머신의 리소스사용 차이


사용되고있는 리소스의 양을 확인할 수 있다.
--no-straem 해주면 계속해서 모니터링하지않고 한 순간만 볼 수 있음

컨테이너의 또하나의 특징으로 컨테이너는 하드웨어의 리소스를 모두 이용할 수 있음

마치 그냥 os에 있는 프로세스처럼 작동함 다만 태그를 통해 격리해놓은것 뿐.. 그 차이를 알고 넘어가자


CPU 제한 걸기


말그대로 CPU의 개수를 제한할 수 있음

vagrant에서 lscpu하면 cpu의 갯수를 2개로 이미 지정해놓은 것을 확인할 수 있다.

docker run --cpus 0.1 -d ubuntu sha256sub /dev/zero
docker ps
docker stats --no-stream


완벽하게 10%는 아니고 넘어갔다가 하거나 할 수 는 있음


--memory 옵션

추가적으로 네트워크와 디스크IO도 제한을 걸 수 있지만 잘 사용하지는 않다


컨테이너에 할당된 cpu나 메모리 변경하기

docker stats --no-straem
docker run -d --cpus 0.1 --memory 100m ubuntu sha256sum /dev/zero
docker update --cpus 0.2 da
docker stats --no-stream
docker update --momory 200m da
docker stats --no-stream

컨테이너는 로그를 남기는가?

docker run -d httpd
docker ps
dockdf exec -it 69 bash
ls
cd logs/
ls
cat httpd.pid

로그를 보고싶지만 실제로그는 없음 컨테이너에는 로그를남기지않음

컨테이너는 불변의 인프라에 맞게 설계가된 가상화임
vm은 mutable 인프라 스트럭쳐 즉 변경이 가능하게 설계된 가상화이다. mutable 은 계속해서 변경을 해주어야해서 packer같은것이 있는것도 있음

컨테이너도 어플리케이션 업데이트를 할 수야 있겠지만 새로운 이미지로 교체하는게 더 빠름

기본 구조 조차도 컨테이너를 갈아끼는거라서 로그를 남기는건 맞지않다 하지만 보안상이든 법적으로 로그기록은 꼭필요함 그래서 이 부분을 어떻게 해결할것인지에 대한 내용

그래서 실제로 로그는 어디에 있냐면 우분투 시스템 즉 도커 호스트에 있음

sudo -i
cd /var/lib/docker/containers/
ls
cd [컨테이너ID]
ls

실습해본 결과 같은 내용인것을 확인할 수 있음

더 간단한 방법으로

docker logs [컨테이너 ID]

그리고 이후 컨테이너를 삭제하고나면 디렉토리와함께 로그는 지워진다. 이것을 남기려는 노력이 필요함 그래서 이 로그를 원격에다가 전송하는 방법이 있음

교재 61페이지에서..

64페이지에 syslog를 통해 남길 수있음
컨테이너의 로그를 syslog서버에 남길 수는 있지만 하지는 않을예정 왜냐하면 나중에 쿠퍼네티스에서 해결가능하기 때문

교재 71페이지.. AWS에다가도 로그를 넘길 수도 있음


환경변수

docker run -it -e A=100 ubuntu

PATH= 이부분은 환경변수가 이미 이미지를 만들면서 만들어진거임

예시

이것도 일정의 환경변수이고 애플리케이션의 작동에 영향을 미침

실제로 컨테이너를 실행할 때

docker run mysql:5.7
docker logs 50


환경변수를 지정해야한다는 내용의 오류메시지를 확인할 수 있다.
우리는 그동안 데이터베이스를 만들어서 초기세팅을 했었는데 그 작업이 결국 환경변수를 세팅하는 것이고 컨테이너도 당연히 환경변수를 세팅해야하는 것이다
어떻게 하는지 알아볼 예정


도커홈페이지에 mysql 또는 mariadb를 들어가보면 초기설정을 어떻게 설정하는지 잘 나와있어서 이런 것들을 해야함

docker run -d -e MYSQL_ROOT_PASSWORD=P@ssw0rd mysql:57
docker ps
docker logs 2e

하면 로그가 매우 많이 보인다
그리고 마지막에 3306포트가 열려있습니다 라고 하고 끝나는 로그를 볼 수 있음

docker ps
docker top 2e
docker exec -it 2e bash
mysql -u root -p				 #자기가 자기한테 접속
docker ps -a
docker rm -f `docker ps -aq`

이번에는 데이터 베이스도 생성한 예제


컨테이너 IP확인

docker run -it ubuntu
Ctrl+pq
docker inspect 16a 		#컨테이너의 상세정보

제일 아래쪽에 보면

docker inspect 16a -f '{{.NetworkSettings.IPAddress}}'

이 명령어를 가지고 컨테이너의 ip를 확인할 수 있다.
이걸 가지고 컨테이너 간에 통신을 할 수도 있음 !

docker attach 16
ip
ctrl+c
docker inspect 160 -f {{ .NetworkSettings.IPAddress }}

보면 순서대로 172.17.0.[2,3,4,5...] 이렇게 진행됨

ubuntu 컨테이너에서..

apt update
apt install mysql-client
y
mysql -h 172.17.0.2 -u root -p

하면 우분투에서 mysql컨테이너로 접속을 할 수 있음

귀찮으면 기본적으로

이런식으로도 가능 mysql 컨테이너에는 기본적으로 클라이언트가 있기때문에

더 간단하게는


DB의 ip를 나중에 웹서버에 등록을 해야하는 과정에서 필요한게

discovery

docker run -it --link 


이렇게 하는 작업이 디스커버리임
이름만 지정하면 내부에서 이름을 가지고 데이터베이스 엔드포인트를 잡아줄 수 있음

또 다른 방법

컨테이너 이름을 지정을 해주고

docker run --link mysqldb mysql:5.7 mysql -h mysqldb -u root -p

하면 바로 접속이 가능
결과

더 세련된 방법



별칭을 사용하는 방법임

이런 작업을 여러번 작업 해보는것을 추천한다고 하심

워드프레스도 당연히 컨테이너 이미지가 있고 환경변수를 어떻게 실행시킬 수 있을지

명령어 2줄로 워드프레스를 올릴 수 있음
db컨테이너 + wordpress 명령어
2줄로 가능함


네트워크에 대한 고민


프라이빗 환경에서는 접속이 되지만


이걸 윈도우에서 접속하면 당연히 접속이 안됨

그래서 포트를 포워딩 해주어야함


도커 호스트랑 연결을 해주는 포트 포워딩을 해주어야함

docker run -p <HOST>:<CONTAINER_PORT>

컨테이너 포트 번호는 바뀔 일이 없음


도커 프록시가 받아서 내부로 전달시켜주는것임

서로 다른 어플리케이션이 같은 포트를 사용할 수 있느냐 그것은 안됨

ss -tnlp
앞에는 호스트 뒤에는 컨테이너의 포트


숙제

나중에 다른 이미지들도 응용가능할 정도로 공부하고 연습해볼 필요가 있다

https://www.drupal.org/
https://hub.docker.com/_/drupal

wordpress가 아니라 이것도 공부해서 한 번 해보도록 하자
1. docker를 사용해서 wordpress 배포
2. docker를 사용해서 drupal 배포

정답




docker run --name wp-db -d -e MYSQL_ROOT_PASSWORD=P@ssw0rd -e 
docker run --name wp-web -d --link wp-db:mysql -e WORDPRESS_DB_HOST=mysql -e WORDPRESS_DB_USER=wpadm -e WORDPRESS_DB_PASSWORD=P@ssw0rd -e WORDPRESS_DB_NAME=wordpress --restart always --cpus 0.5 --memory 500m -p 80:80 wordpress:5-apache

0개의 댓글