09/08(금) 도커 2

Yuri JI·2022년 9월 8일
0

Kakao Cloud School

목록 보기
7/27

왜 도커를 사용하는가?
복잡한 linux application을 여러 Container로 통합하여 실행할 수 있음 -> microservice

개발, 테스트, 서비스 환경을 하나로 통합하여 효율적 관리가 가능하다 !
통합 : 하나로 합친다 X, 개발 테스트 서비스가 모두 같은 환경을 만든다.

how ? Image(&Container)를 전 세계 사람들과 공유

⭐ 컨테이너의 실체

  1. 이미지로부터 만들어진다.
  2. OS로부터 모든 요소들이 포함된(Application의 소스파일까지) 하나의 패키징 > OCI
  3. docker run .. 이미지명 태그 > Image의 snapshot을 생성한다.
  4. 이 스냅샷을 /var/lib/docker에 저장

  1. Image의 snapshot을 만든다. (Image 원본을 바로 사용하지않음 !) 이것을 /var/lib/docker에 저장
  2. image(정적) vs container(동적)

    💭 Container는 process다 !
    ps -ef | grep ~ 으로 조회가능 !

images를 snapshot을 찍어서 복제
그 위에 프로세스를 얹히면 Container !

근데 이 컨테이너에는 커널이 없어서, 도커엔진이 hostOS의 커널을 빌려쓴다.


  • 가상화 기술의 두 주류
  1. vm
  2. container
    : vm가상화보다 빠르고, 가벼운 경량화 기술 (micro VM)

공통점 : 둘 다 이미지를 사용한다.
VM은 이미지를 Virtual box로, 도커는 도커엔진으로 돌린다. .. 하이퍼바이저인가 >

VMDocker
특징 1. 커널 유무독립된 커널커널이 없다. HostOS에게 커널을 빌린다.
특징 2.테스트2테스트3
테스트1테스트2테스트3

⭐ 컨테이너 안에는 OS를 포함한 Application 소스까지 다 들어가있다. (커널은 없다 ! -> 그래서 가볍다)
⭐ docker engine은 hostos의 커널을 빌려쓴다.
그래서 컨테이너는 서버용이라기보다는 애플리케이션 배포용..?


LXC (Linux Container) 기술을 이용해서 만든게 docker

docker의 3대 기술

  • namespaces

  • cgroups

  • chroot
    시스템에서 PID=1은 systemd.
    컨테이너는 PID=1이 존재하지만 systemd가 아닌 그 컨테이너 자체다. Container가 PID=1 소유. (OS인척)
    그래서 별도의 prompt가 존재한다. (독립된 공간)

+) fuse(filesystem userspace) package
-> /data 디렉토리를 mount 시키고 -> daemon으로 실행한다. => fuse가 ???한 환경 만들어줌

우리는 OS 세팅할 때 항상 리소스를 잡았다.

그 리소스는 cgorup가 관리

  • cgroup ( 컨테이너에 자원을 할당하는 기술 )
    4대 resource가 할당된다.(cpu, memory, disk)가 할당을 한다. (network는 다른 애가 할당)
    호스트가 가진 자원을 무제한으로 컨테이너에 할당할 수 있다. 따라서 자원 할당 제한을 할 줄 알아야한다.

기본적으로 cgroup의 역할은 컨테이너에게 자원 할당.
네트워크는 namespace가 관리

  • namespace
    network -> ns(-> IP, MAC, IPC, ...), mount, UID

docker run -d -m=100m -p 8001:80 --name=myweb nginx:1.23-alpine

nginx 컨테이너 띄우면서 80번 포트 열어줘, 그리고 우분투의 8001번 열어서 컨테이너랑 연결해줘... ??

나(윈도우) -> 192.168.56.101:8001 -> 172.0.0.2:80로 바뀌면서 컨테이너로 접속

192.168.56.101은 우분투의 주소니까ㅏㅏ 8001 포트로 접속해야한다.

여기서 활용하는 기술이 NAT다.
위의 예시에서는 NAT가 IP 주소와 포트번호를 둘 다 변경했다.

-p ( != port, publish !) : 8001번으로 들어온 걸 80번으로 연결해줘


chroot -> 독립된 / 를 제공한다. 독립된 컨테이너 환경
cgroups -> 생성된 컨테이너에 자원 할당을
network namespaces -> 컨테이너에 IP를 배치하여 독립된 가상 환경 제공

  • fuse(filesystem userspace>) : 도 함께 가상환경을 제공한다

Docker의 핵심기술
-> 하드웨어 가상화가 없이 격리된 환경에서 실행되는 프로세스 즉, 프로세스의 표준화된 격리 ! = 컨테이너

코드 구성 종속성(환경일관성) 런타임엔진 -> 한 박스에 넣는다. == 이미지를 만든다.

도커엔진의 3가지 구성요소

  1. dockerd -> docker CLI(명령어) 수행 : 사용자의 명령어를 수행한다.
  2. containerd
  3. runC
    ------ docker engine -----
  4. HostOS(ubuntu) -> kernel -> LXC 기술

docker 설치

  • 전제조건
  1. 커널버전 3.1이상, 64비트

  2. 도커 관련된 패키지를 설치

sudo apt -y install \
apt-transport-https \
ca-certificates \
curl \
software-properties-common
  1. GPG키 추가
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

  1. 추가된 GPG키 확인

sudo rm -rf /var/lib/dpkg/lock-frontend

데몬들끼리 소켓 통신

docker 명령어 사용할 때 앞에 sudo 생략

sudo usermod -aG docker [user명]
sudo systemctl daemon-reload
sudo systemctl enable docker

브릿지 OSI 2계층


  • docker info

Network : bridge host ipvlan null overlay
bridge : docker0 -> docker network ls 로 확인 가능
기본 네트워크로 bridge를 사용한다.

hostos1과 hostos2와의 통신은 불가능하다.
bridge 네트워크는 로컬만 지원한다. 그러니 설정을 바꾸자.
bridge local overlay(서로 다른 호스트 간의 통신)


개발팀으로부터 요청 : ubuntu18.02 버전에 특정 application을 실행하고자 한다. -> image 생성해 주세요. -> Docker file
-> ubuntu image download(pull) -> docker run -> contatiner 생성-> docker exec ~ -> PID=1(own) host(ps)
-> chroot / cgroup / namespace
-> 직접 필요한 패키지들을 설치 (모든 image는 기본적으로 online package 설치 가능... centos(yum), ubuntu(apt))
-> apt -y update 우선 수행

docker hub에서 image 검색

  • 보통 태그는 버전을 사용한다. 한 줄에 있는 단어들은 모두 같은 말이다.

이미지:태그
ubunut:18.04

우분투 이미지 다운받기

docker pull ubuntu:18.04

  • 그림을 보면 3줄(레이어라고 함)이 뜬다. => 이미지는 계층적 구조임을 알 수 있다.

  • 이미지는 불변이다 ? ... 자꾸 뭐가 안 바뀐대.)..
    -> 새로운 이미지로 저장 가능 (docker commit)


container run -> run time

  • 우분투 컨테이너 시작

  • 컨테이너의 이름은 호스트네임!

  • exit 치고 컨테이너 나오면 컨테이너가 죽는다.
  • ctl + p + q 누르면 컨테이너 안죽고 그냥 나온다. (이거 써라)
  • dockerp ps -a에서도 보이지않게 나 아예 없애고싶어 (이게 무슨 상태여)
docker stop [container_name]
docker rm [container_name]
  • docker ip 주소확인하기
docker inspect [container name | container id] | grep -i ipaddress
  • 그림에서 윗 동네는 docker images ~ 로 명령어 시작 아랫 동네(컨테이너는 ) docker ~ 로 만 시작
  • 실습 1
apt -y install net-tools : ifconfig
apt -y install iputils-ping : ping
  • 이미지 pull 받기 전에 꼭 dockerhub에서 이미지를 확인하고 쓴다.

docker로 mysql 컨테이너 띄우기

  1. docker pull mysql:5.7-debian, mysql image 다운로드


    많은 레이어들을 볼 수 있다.

  2. docker run -it -e MYSQL_ROOT_PASSWORD=1234 mysql:5.7-debian bash , 컨테이너 접속

  3. cat /etc/os-release , os 버전 확인

  4. /etc/init.d/mysql start , 데몬 실행

  5. mysql -uroot -p



위 그림 상태는 포트가 열렸지만 접속이 되는 상태는 아님


mariadb:10.2의 DB를 컨테이너로 실행하고, item이라는 데이터베이스에 workbench로 연결하기

<환경변수>
MARIADB_ROOT_PASSWORD=1234
MARIADB_DATABASE=item
-p 13306:3306

# -p 13306:3306 = workbench 연결위한 포트 설정
  1. mariadb 컨테이너 생성, 이미지는 없으면 알아서 이미지 다운받아준다.
docker run -d -e MARIADB_ROOT_PASSWORD=1234 -e MARIADB_DATABASE=item --name=itemdb -p 13306:3306 mariadb:10.2

1-1. 포트 확인

sudo netstat -nlp | grep 13306
  1. 컨테이너 실행
docker exec -it itemdb bash
  1. show databases; 하면 item db가 생성된 것을 볼 수 있다 ! 1번 명령어에서 알아서 데몬켜고 데이터베이스를 만든 것이다.
MariaDB [(none)]> GRANT ALL PRIVILEGES ON empdb.* TO emp_admin@'%' IDENTIFIED BY                     'docker4u';
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> select user, host from mysql.user;
+-----------+-----------+
| user      | host      |
+-----------+-----------+
| emp_admin | %         |
| root      | %         |
| emp_admin | localhost |
| root      | localhost |
+-----------+-----------+
4 rows in set (0.00 sec)

MariaDB [(none)]> flush privileges;
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> exit
Bye
  1. 실습위한 데이터 받아오기
apt-get install git -y
git clone https://github.com/brayanlee/emp_db.git
cd emp_db/
ls
mysql -u emp_admin -p empdb
password: (docekr4u)
MariaDB [empdb]> status;
source employees.sql # 수십만건의 오버 워크로드 발생
show tables;
select * from dept_emp;

cadvisor

구글에서 제공하는 가벼운 모니터링 툴

  1. cAdvisor 컨테이너 생성 및 실행
docker run \
>--volume=/:/rootfs:ro \
>--volume=/var/run:/var/run:rw \
>--volume=/sys:/sys:ro \
>--volume=/var/lib/docker/:/var/lib/docker:ro \
>--publish=9559:8080 \
>--detach=true \
>--name=cadvisor \
>google/cadvisor:latest
  1. 9559 포트 열렸는지 확인
sudo netstat -nlp | grep 9559
  1. docker ps로 컨테이너 실행 확인

docker image layer

-> 레이어의 개수는 라인 수에 따라 결정된다 ? ?
https://woochan-autobiography.tistory.com/468


images를 snapshot을 찍어서 복제
그 위에 프로세스를 얹히면 Container !

근데 이 컨테이너에는 커널이 없어서, 도커엔진이 hostOS의 커널을 빌려쓴다.

docker proxy 가 NAT ? ? 어떤 두 가지를 해준
다..//


도커.. 프록시... 앞은 PID

도커 프록시가 몇번 포트에서 몇번 포트 열고 뭐 이런 내용 찾아서 추가하기


Nginx

-> 웹서버, 웹서비스, proxy

nginx 띄우기

docker pull nginx : 최신버전 다운받아지는데 너무 무겁다 ! 지양하자

yji@hostos1:~$ docker pull nginx:1.21.1-alpine
yji@hostos1:~$ docker images | grep nginx
nginx             1.21.1-alpine   1318bf5f63b4   12 months ago   22.8MB

yji@hostos1:~$ docker run -d --name=myweb1 -p 8001:80 nginx:1.23.1-alpine
yji@hostos1:~$ sudo netstat -nlp | grep 8001
[sudo] password for yji:
tcp        0      0 0.0.0.0:8001            0.0.0.0:*               LISTEN      11883/docker-proxy
tcp6       0      0 :::8001                 :::*                    LISTEN      11888/docker-proxy

yji@hostos1:~$ ps -ef | grep 11883
root       11883     866  0 16:04 ?        00:00:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 8001 -container-ip 172.17.0.4 -container-port 80
yji        11996   10578  0 16:05 pts/4    00:00:00 grep --color=auto 11883

작동 확인

  1. http://192.168.56.101:8001로 접속
  2. curl localhost:8001 명령 실행

실습 3.

  • 개발팀으로부터 개발 소스를 제공 받음
  • 해당 application을 실행할 수 있는 image를 이용하여 소스와 함께 Dockerfile 작성
  • build time -> Image 생성

1. docker 명령어 사용 ( docker cp )

yji@hostos1:~$ mkdir LABs && cd $_
yji@hostos1:~/LABs$ mkdir nginx-test && cd $_

yji@hostos1:~/LABs/nginx-test$ vim index.html
yji@hostos1:~/LABs/nginx-test$ docker cp index.html myweb1:/usr/share/nginx/html/index.html
yji@hostos1:~/LABs/nginx-test$ docker cp logo.PNG myweb1:/usr/share/nginx/html/logo.PNG

  • index.html
<!DOCTYPE html>
<html>
        <head>
<style>
body {
        background-image:url('./logo.PNG');
}
</style>
        </head>
        <body>
                <h1>He llO  o  o o  oo </h1>
        </body>
</html>

2. Dockerfile 작성

  • Dockerfile
FROM nginx:1.23.1-alpine
COPY index2.html /usr/share/nginx/html/index.html
COPY docker_logo.png /usr/share/nginx/html/docker_logo.png
EXPOSE 80/tcp
CMD ["nginx", "-g", "daemon off;"]

⭐⭐ 우리가 라인 5줄 적어서 레이어도 5개 쌓인다. (Step x./5)

yji@hostos1:~/LABs/nginx-test$ vim Dockerfile
yji@hostos1:~/LABs/nginx-test$ docker build -t myweb:1.0 .
Sending build context to Docker daemon  67.58kB
Step 1/5 : FROM nginx:1.23.1-alpine
 ---> 804f9cebfdc5
Step 2/5 : COPY index.html myweb1:/usr/share/nginx/html/index.html
 ---> ab998aedd28b
Step 3/5 : COPY logo.PNG myweb1:/usr/share/nginx/html/logo.PNG
 ---> e172e436139c
Step 4/5 : EXPOSE 80/tcp
 ---> Running in c7769671e997
Removing intermediate container c7769671e997
 ---> adf6d35d5e5e
Step 5/5 : CMD ["nginx", "-g", "daemon-off;"]
 ---> Running in 09993ef20859
Removing intermediate container 09993ef20859
 ---> 402d9f00a900
Successfully built 402d9f00a900
Successfully tagged myweb:1.0

# Docker 파일로 만든 myweb:1.0 이미지로 myweb2 컨테이너 실행하기
yji@hostos1:~/LABs/nginx-test$ docker run -d -p 8002:80 --name myweb2 myweb:1.0

# 컨테이너 잘 동작하는지 확인
yji@hostos1:~/LABs/nginx-test$ curl localhost:8002

실습4

강사로부터 개발완료된 소스를 제공 받는다. 이 소스를 포함하는 nginx 기반의 myweb:2.0 build 하시오.
반드시 image build 후 생성한 image로 container 실행 테스트를 수행해야 한다.

  1. 강사님이 주신 파일을 폴더 안으로 이동시킨다.
  2. Dockerfile 작성
FROM nginx:1.23.1-alpine
RUN mkdir -p /usr/share/nginx/html/assets
RUN mkdir -p /usr/share/nginx/html/css
RUN mkdir -p /usr/share/nginx/html/js

COPY assets /usr/share/nginx/html/assets
COPY css /usr/share/nginx/html/css
COPY js /usr/share/nginx/html/js
COPY index.html /usr/share/nginx/html/index.html
EXPOSE 80/tcp 

CMD ["nginx", "-g", "daemon off;"]
  1. docker build -t myweb:2.0 . : 이미지 생성

  2. docker run -d -p 8003:80 --name myweb3 myweb:2.0

질문

docker cp 명령어에서는 myapp1:/usr 식으로 적지만,
Dockerfile에서는 /usr 로 적으면 된다. !


하이퍼바이저 기반의 도커 엔진 ?

LXC의 역할

라우터 vs 스위치 vs 허브 -> key point

docker ps 
docekr stop [컨테이너이름]
docker rm [컨테이너이름]

  • putty랑 cadviser 안되던 문제..
    네트워크(emp0s8) 아래와 같이 설정하고 껐다 켜기

? docker commit을 어떤 상황에서 써야하는지 ?

image = layer N -> build time -> line(명령줄) -> Step N = layer * n
-> 정지된 컨테이너와 같다. -> class와 같다

  • exec :작업, attach: 로그? ...
MARIADB_ROOT_PASSWORD=1234
MARIADB_DATABASE=item
-p 13306:3306
-p 13306:3306 = workbench 연결위한 포트 설정
3306은 우리가 로컬에서 사용하고있어서 그런건지? 
profile
안녕하세요 😄

0개의 댓글