왜 도커를 사용하는가?
복잡한 linux application을 여러 Container로 통합하여 실행할 수 있음 -> microservice
개발, 테스트, 서비스 환경을 하나로 통합하여 효율적 관리가 가능하다 !
통합 : 하나로 합친다 X, 개발 테스트 서비스가 모두 같은 환경을 만든다.
how ? Image(&Container)를 전 세계 사람들과 공유
💭 Container는 process다 !
ps -ef | grep ~ 으로 조회가능 !
images를 snapshot을 찍어서 복제
그 위에 프로세스를 얹히면 Container !
근데 이 컨테이너에는 커널이 없어서, 도커엔진이 hostOS의 커널을 빌려쓴다.
공통점 : 둘 다 이미지를 사용한다.
VM은 이미지를 Virtual box로, 도커는 도커엔진으로 돌린다. .. 하이퍼바이저인가 >
VM | Docker | |
---|---|---|
특징 1. 커널 유무 | 독립된 커널 | 커널이 없다. HostOS에게 커널을 빌린다. |
특징 2. | 테스트2 | 테스트3 |
테스트1 | 테스트2 | 테스트3 |
⭐ 컨테이너 안에는 OS를 포함한 Application 소스까지 다 들어가있다. (커널은 없다 ! -> 그래서 가볍다)
⭐ docker engine은 hostos의 커널을 빌려쓴다.
그래서 컨테이너는 서버용이라기보다는 애플리케이션 배포용..?
LXC (Linux Container) 기술을 이용해서 만든게 docker
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의 역할은 컨테이너에게 자원 할당.
네트워크는 namespace가 관리
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를 배치하여 독립된 가상 환경 제공
Docker의 핵심기술
-> 하드웨어 가상화가 없이 격리된 환경에서 실행되는 프로세스 즉, 프로세스의 표준화된 격리 ! = 컨테이너
코드 구성 종속성(환경일관성) 런타임엔진 -> 한 박스에 넣는다. == 이미지를 만든다.
커널버전 3.1이상, 64비트
도커 관련된 패키지를 설치
sudo apt -y install \
apt-transport-https \
ca-certificates \
curl \
software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
추가된 GPG키 확인
sudo rm -rf /var/lib/dpkg/lock-frontend
데몬들끼리 소켓 통신
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 우선 수행
이미지:태그
ubunut:18.04
docker pull ubuntu:18.04
그림을 보면 3줄(레이어라고 함)이 뜬다. => 이미지는 계층적 구조임을 알 수 있다.
이미지는 불변이다 ? ... 자꾸 뭐가 안 바뀐대.)..
-> 새로운 이미지로 저장 가능 (docker commit
)
container run -> run time
docker stop [container_name]
docker rm [container_name]
docker inspect [container name | container id] | grep -i ipaddress
apt -y install net-tools : ifconfig
apt -y install iputils-ping : ping
docker pull mysql:5.7-debian
, mysql image 다운로드
많은 레이어들을 볼 수 있다.
docker run -it -e MYSQL_ROOT_PASSWORD=1234 mysql:5.7-debian bash
, 컨테이너 접속
cat /etc/os-release
, os 버전 확인
/etc/init.d/mysql start
, 데몬 실행
mysql -uroot -p
위 그림 상태는 포트가 열렸지만 접속이 되는 상태는 아님
<환경변수>
MARIADB_ROOT_PASSWORD=1234
MARIADB_DATABASE=item
-p 13306:3306
# -p 13306:3306 = workbench 연결위한 포트 설정
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
docker exec -it itemdb bash
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
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;
구글에서 제공하는 가벼운 모니터링 툴
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
sudo netstat -nlp | grep 9559
docker ps
로 컨테이너 실행 확인-> 레이어의 개수는 라인 수에 따라 결정된다 ? ?
https://woochan-autobiography.tistory.com/468
images를 snapshot을 찍어서 복제
그 위에 프로세스를 얹히면 Container !
근데 이 컨테이너에는 커널이 없어서, 도커엔진이 hostOS의 커널을 빌려쓴다.
docker proxy 가 NAT ? ? 어떤 두 가지를 해준
다..//
도커.. 프록시... 앞은 PID
도커 프록시가 몇번 포트에서 몇번 포트 열고 뭐 이런 내용 찾아서 추가하기
-> 웹서버, 웹서비스, proxy
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
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
<!DOCTYPE html>
<html>
<head>
<style>
body {
background-image:url('./logo.PNG');
}
</style>
</head>
<body>
<h1>He llO o o o oo </h1>
</body>
</html>
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
강사로부터 개발완료된 소스를 제공 받는다. 이 소스를 포함하는 nginx 기반의 myweb:2.0 build 하시오.
반드시 image build 후 생성한 image로 container 실행 테스트를 수행해야 한다.
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;"]
docker build -t myweb:2.0 .
: 이미지 생성
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 [컨테이너이름]
? 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은 우리가 로컬에서 사용하고있어서 그런건지?