: 복잡한 Linux Application을 여러 container로 통합하여 실행할 수 있다.
: 개발, 테스트, 서비스 환경을 하나로 통합하여 효율적 관리가 가능하기 때문이다. 통합한다는 것은 똑같은 환경에서 개발, 테스트 등을 할 수 있다는 의미이다.
: image(&container)를 전세계 사람들과 공유한다. 공유는 GitHub와 유사한 방식(open share)의 Docker Hub를 제공한다.
: 하드웨어 가상화가 없이 격리된 환경에서 실행되는 프로세스
: "프로세스의 표준화된 격리"
프론트 쪽에 접속하는 사용자 수가 갑자기 늘어난다. 서버가 느려지면 사용자는 사용하지 않는다. 프론트를 설계할 때 고려해야 할 사항(사용자 수 등)을 고려해야 한다.
: Process -> ps -ef로 조회가 된다.
Dockerfile을 통해 image을 개발하고, 개발된 image로 container를 실행한다.
: container는 VM 가상화보다 훨씬 빠르고 가벼운 경량화 기술이다.(micro VM)
container와 vm 모두 이미지를 사용한다. vm은 virtual box로 이미지를 돌리고, container는 docker로 돌린다.
: vm에는 guest OS(커널)가 존재한다. -> VM은 독립된 커널로 동작한다. 따라서 무겁다.
container는 OS(Ubuntu)를 깔아놓고 container engine을 올리면 그 위에서 OS가 동작한다. container에는 커널이 없다. host OS(Ubuntu)의 커널을 빌려서 사용한다.
LXC를 응용해서 만든 것이 docker이다.
chroot(change root) - 바로 독립된 container 환경을
시스템에서 PID=1이 존재하지만 systemd가 아닌 container 자체가 PID=1을 소유한다. -> OS
-> 별도의 prompt가 존재한다. 독립된 영역(격리된 영역 = fw)을 갖는다.
fuse(filesystem userspace) package - /data 디렉터리를 mount 시키고 daemon으로 실행시킨다.
cgroups(control group) - 생성된 container에 자원 할당을
: 컨테이너에 자원 할당하는 커널 기술이다. -> 4대 resource(cpu, memory, disk)
host가 가진 자원을 무제한을 사용할 수 있기 때문에 제한을 해야 한다.
namespace - container에 IP 등을 배치하여 독립된 가상 환경을
network ns(IP, MAC, IPC, ...) mount, UID, ... 다양한 기술을 포함할 수 있게 해준다.
IP나 MAC을 제공하는 것을 sandbox라고 부른다.
os부터 application, source가 모두 포함된 하나의 패키징
-> OCI를 통해 묶는다.
: docker run -d -m=100m -p 8001:80 --name=myweb nginx:1.23-alpine
명령어로 컨테이너 생성 후, 접근할 때 과정이다.
도커, 컨테이터 빌드업! 28 page 참조
서로 통신을 하고 docker engine은 kernel과 통신한다. 통신은 docker.sock으로 통신한다.
dockerd (docker daemon)
: docker CLI(명령어)를 받아들이고 수행한다.
containerd
: container의 lifecycle을 관리한다.
runC
: container를 생성한다.
=> 이 셋 밑에 HostOS(ubuntu)와 kernel이 존재하고, LXC 기술이 사용된다.
전제조건
: kernel version 3.1 이상, 64bitkevin@hostos1:~$ uname -ar Linux hostos1 5.15.0-46-generic #49~20.04.1-Ubuntu SMP Thu Aug 4 19:15:44 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
## 업데이트
# lock 걸리는 경우에는 sudo rm -rf [lock 파일]
kevin@hostos1:~$ sudo apt -y update
## docker 설치를 위한 package
kevin@hostos1:~$ sudo apt -y install \
> apt-transport-https \
> ca-certificates \
> curl \
> software-properties-common
## 공식 GPG key 추가
kevin@hostos1:~$ sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
OK
## Docker Release (CE deb)가 있는지 확인한다.
kevin@hostos1:~$ sudo apt-key fingerprint
/etc/apt/trusted.gpg
--------------------
pub rsa4096 2017-02-22 [SCEA]
9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88
uid [ unknown] Docker Release (CE deb) <docker@docker.com>
sub rsa4096 2017-02-22 [S]
## 데비안 계열의 도커 repository PPA 추가
kevin@hostos1:~$ sudo add-apt-repository \
> "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
> $(lsb_release -cs) \
> stable"
## 추가된 것 확인하기
kevin@hostos1:~$ tail /etc/apt/sources.list
## 업데이트하고, 도커 커뮤니티 에디션 설치
kevin@hostos1:~$ sudo apt -y update
kevin@hostos1:~$ apt-cache policy docker-ce
Installed: (none)
Candidate: 5:20.10.17~3-0~ubuntu-focal
kevin@hostos1:~$ sudo apt-get -y install docker-ce
## 설치 확인
kevin@hostos1:~$ sudo docker version
## 권한 변경
# 계속 sudo를 치면 귀찮기 때문에
kevin@hostos1:~$ sudo usermod -aG docker kevin
kevin@hostos1:~$ sudo systemctl daemon-reload
kevin@hostos1:~$ sudo systemctl enable docker
kevin@hostos1:~$ sudo systemctl restart docker
kevin@hostos1:~$ sudo reboot
## sudo 없이 docker version 확인하기
kevin@hostos1:~$ docker version
kevin@hostos1:~$ ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:19:03:07:66 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
kevin@hostos1:~$ route
Destination Gateway Genmask Flags Metric Ref Use Iface
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
kevin@hostos1:~$ docker info
# registry에 docker.io가 등록되어 있기 때문에 pull을 할 때 바로 받을 수 있다.
bridge 네트워크는 로컬에서만 통신이 가능하다. hostos1과 hostos2 컨테이너끼리는 통신이 불가능하다. overlay를 별도로 이용해야 host 간의 container 통신이 가능해진다.
이미지에서 tag가 붙는데 버전이다.
ubuntu:18.04
## image download
kevin@hostos1:~$ docker pull ubuntu:18.04
kevin@hostos1:~$ docker pull ubuntu:14.04
kevin@hostos1:~$ docker pull ubuntu:16.04
16.04: Pulling from library/ubuntu
58690f9b18fc: Pull complete
b51569e7c507: Pull complete
da8ef40b9eca: Pull complete
fb15d46c38dc: Pull complete
Digest: sha256:91bd29a464fdabfcf44e29e1f2a5f213c6dfa750b6290e40dd6998ac79da3c41
Status: Downloaded newer image for ubuntu:16.04
docker.io/library/ubuntu:16.04
이미지는 계층 구조
pull을 받을 때 여러개를 받는 것을 볼 수 있다.
여러 개를 다운로드 받고 하나로 합친다.(Merge)
layer 여러개로 이루어져 있다.이미지는 수정 불가능
image를 수정하면 새로운 image로 저장 가능하다.
새롭게 image를 생성하는 것이다.(commit)
build time -> line(명령줄) -> Step N = layer N
layer는 Dockerfile의 줄 수와 연관이 되어 있다.
kevin@hostos1:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 18.04 35b3f4f76a24 33 hours ago 63.1MB
ubuntu 16.04 b6f507652425 12 months ago 135MB
ubuntu 14.04 13b66b487594 17 months ago 197MB
: 용량이 작은 것을 알 수 있다.
## echo
kevin@hostos1:~$ docker run -it ubuntu:18.04 echo 'hello docker!'
hello docker!
## container로 들어가기
kevin@hostos1:~$ docker run -it ubuntu:18.04 bash
root@2004c08eea02:/# pwd
/
root@2004c08eea02:/# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 05:00 pts/0 00:00:00 bash
root 12 1 0 05:00 pts/0 00:00:00 ps -ef
## OS 확인하기
root@2004c08eea02:/# cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.6 LTS (Bionic Beaver)"
...
## ip 확인하기
root@2004c08eea02:/# ifconfig
bash: ifconfig: command not found ## 컨테이너를 최대한 가볍게 유지하기 위해서 없다.
root@2004c08eea02:/# apt -y update
root@2004c08eea02:/# apt -y install net-tools
root@2004c08eea02:/# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255
...
## 나가기
root@2004c08eea02:/# exit
exit
kevin@hostos1:~$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2004c08eea02 ubuntu:18.04 "bash" 8 minutes ago Exited (130) 5 seconds ago dreamy_turing
1f146748297a ubuntu:18.04 "echo 'hello docker!'" 9 minutes ago Exited (0) 9 minutes ago stoic_wilson
## 컨테이너 다시 시작하기
kevin@hostos1:~$ docker start 2004c08eea02
2004c08eea02
## up 상태로 바뀐다
kevin@hostos1:~$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2004c08eea02 ubuntu:18.04 "bash" 11 minutes ago Up 37 seconds dreamy_turing
1f146748297a ubuntu:18.04 "echo 'hello docker!'" 13 minutes ago Exited (0) 13 minutes ago stoic_wilson
## 만들었던 컨테이너에 다시 들어가기
kevin@hostos1:~$ docker exec -it 2004c08eea02 bash
root@2004c08eea02:/#
exit으로 나가면 container를 stop 한 것이다.(ctrl + P + Q)
다시 container 안으로 들어갈 때는 exec를 해야 한다.
run을 하면 새로운 container가 만들어진다.
## container 멈추기
kevin@hostos1:~$ docker stop 2004c08eea02
2004c08eea02
## container 삭제하기
kevin@hostos1:~$ docker rm 2004c08eea02
2004c08eea02
## 삭제 되었는지 확인하기
kevin@hostos1:~$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1f146748297a ubuntu:18.04 "echo 'hello docker!'" 16 minutes ago Exited (0) 16 minutes ago stoic_wilson
## 터미널 1
kevin@hostos1:~$ docker run -it ubuntu:18.04 bash
root@cd56c674eda5:/# apt -y update
root@cd56c674eda5:/# apt -y install net-tools
root@cd56c674eda5:/# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255
...
root@cd56c674eda5:/# apt -y install iputils-ping
root@cd56c674eda5:/# ping 192.168.56.1
## 터미널 2
kevin@hostos1:~$ docker run -it centos:7 bash
[root@2efbb769b257 /]# yum -y update
[root@2efbb769b257 /]# yum -y install net-tools
[root@2efbb769b257 /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.3 netmask 255.255.0.0 broadcast 172.17.255.255
...
## ping 확인
[root@2efbb769b257 /]# ping 192.168.56.1
[root@2efbb769b257 /]# ping 172.17.0.2
## 터미널 3
kevin@hostos1:~$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2efbb769b257 centos:7 "bash" 5 minutes ago Up 5 minutes hungry_blackwell
cd56c674eda5 ubuntu:18.04 "bash" 14 minutes ago Up 14 minutes sleepy_wiles
kevin@hostos1:~$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2efbb769b257 centos:7 "bash" 5 minutes ago Up 5 minutes hungry_blackwell
cd56c674eda5 ubuntu:18.04 "bash" 14 minutes ago Up 14 minutes sleepy_wiles
## centos ip 확인하기
kevin@hostos1:~$ docker inspect 2efbb769b257 | grep -i ipaddress
"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.3",
"IPAddress": "172.17.0.3",
## ubuntu ip 확인하기
kevin@hostos1:~$ docker inspect cd56c674eda5 | grep -i ipaddress
"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.2",
"IPAddress": "172.17.0.2",
이미지 명령을 쓸 때는 docker image ~ 로 사용한다.
컨테이너일 때는 생략해서 쓴다.
ex) docker image inspect ~ , docker inspect ~
hostos1에서 ifconfig 했을 때 container 개수에 따라서 vet(virtual ethernet)가 생긴다.
kevin@hostos1:~$ ifconfig veth8cd372e: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet6 fe80::94cd:86ff:fe1b:c1d3 prefixlen 64 scopeid 0x20<link> ether 96:cd:86:1b:c1:d3 txqueuelen 0 (Ethernet) RX packets 4202 bytes 240179 (240.1 KB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 5203 bytes 27178929 (27.1 MB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 vethd66430f: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet6 fe80::2067:66ff:fefd:8ca4 prefixlen 64 scopeid 0x20<link> ether 22:67:66:fd:8c:a4 txqueuelen 0 (Ethernet) RX packets 11080 bytes 610046 (610.0 KB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 13182 bytes 80436056 (80.4 MB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
## image download
kevin@hostos1:~$ docker pull mysql:5.7-debian
## password 설정하고, 안으로 들어가기
kevin@hostos1:~$ docker run -it -e MYSQL_ROOT_PASSWORD=pass123# mysql:5.7-debian bash
root@85ab3f81b2ea:/#
## os 확인하기
root@85ab3f81b2ea:/# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 10 (buster)"
NAME="Debian GNU/Linux"
...
## daemon 실행하고, 들어가기
root@85ab3f81b2ea:/# /etc/init.d/mysql start
root@85ab3f81b2ea:/# mysql -uroot -p
=> 현재는 NAPT가 없기 때문에 외부접근이 되지 않는다. 따라서 실행할 때 -p 옵션을 넣어주면 외부와 통신할 수 있게 된다.
## mariadb image download하고, container 생성하기
kevin@hostos1:~$ docker run -d -e MARIADB_ROOT_PASSWORD=pass123# -e MARIADB_DATABASE=item --name=itemdb -p 13306:3306 mariadb:10.2
## container 상태 확인하기
kevin@hostos1:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
601d80ef1f75 mariadb:10.2 "docker-entrypoint.s…" 29 seconds ago Up 26 seconds 0.0.0.0:13306->3306/tcp, :::13306->3306/tcp itemdb
## 포트 확인하기
kevin@hostos1:~$ sudo netstat -nlp | grep 13306
[sudo] password for kevin:
tcp 0 0 0.0.0.0:13306 0.0.0.0:* LISTEN 6505/docker-proxy
kevin@hostos1:~$ ps -ef | grep 6505
root 6505 956 0 15:05 ? 00:00:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 13306 -container-ip 172.17.0.3 -container-port 3306
## 들어가서 mariadb 실행하기
kevin@hostos1:~$ docker exec -it itemdb bash
root@601d80ef1f75:/# mysql -uroot -p
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| item |
| mysql |
| performance_schema |
+--------------------+
4 rows in set (0.01 sec)
## cAdvisor download
kevin@hostos1:~$ 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
## 포트 확인
kevin@hostos1:~$ sudo netstat -nlp | grep 9559
[sudo] password for kevin:
tcp 0 0 0.0.0.0:9559 0.0.0.0:* LISTEN 6937/docker-proxy
## 실행되었는지 확인
kevin@hostos1:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5b1d36956841 google/cadvisor:latest "/usr/bin/cadvisor -…" 20 seconds ago Up 19 seconds 0.0.0.0:9559->8080/tcp, :::9559->8080/tcp cadvisor
브라우저에서 192.168.56.101:9559 접속해서 확인한다.
## database 생성하기
MariaDB [(none)]> create database empdb;
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| empdb |
| information_schema |
| item |
| mysql |
| performance_schema |
+--------------------+
5 rows in set (0.00 sec)
MariaDB [(none)]> grant all privileges on empdb.*
-> to emp_admin@localhost identified by 'docker_4U'
-> with grant option;
MariaDB [(none)]> grant all privileges on empdb.* to emp_admin@'%' \
-> identified by 'docker_4U';
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;
MariaDB [(none)]> exit;
Bye
## over workload 발생 코드 가져오기
root@601d80ef1f75:/# apt-get update
root@601d80ef1f75:/# apt-get install git -y
root@601d80ef1f75:/# git clone https://github.com/brayanlee/emp_db.git
root@601d80ef1f75:/# cd emp_db/
root@601d80ef1f75:/emp_db# ls
Changelog employees.sql employees_partitioned.sql employees_partitioned_5.1.sql images load_departments.dump load_dept_emp.dump load_dept_manager.dump load_employees.dump sakila
root@601d80ef1f75:/emp_db# mysql -u emp_admin -p empdb
MariaDB [empdb]> status;
MariaDB [empdb]> source employees.sql
MariaDB [empdb]> show tables;
## nginx download
kevin@hostos1:~$ docker pull nginx:1.23.1-alpine
## 용량 확인
kevin@hostos1:~$ docker images | grep nginx
nginx 1.23.1-alpine 804f9cebfdc5 4 weeks ago 23.5MB
## nginx 시작하기
kevin@hostos1:~$ docker run -d --name=myweb1 -p 8001:80 nginx:1.23.1-alpine
b51bfa64b24ed5f0bc13e0c0e1e8f42e621338361d4a530131db4f6b79798476
## port 열렸는지 확인
kevin@hostos1:~$ sudo netstat -nlp | grep 8001
[sudo] password for kevin:
tcp 0 0 0.0.0.0:8001 0.0.0.0:* LISTEN 8470/docker-proxy
tcp6 0 0 :::8001 :::* LISTEN 8476/docker-proxy
kevin@hostos1:~$ ps -ef | grep 8470
root 8470 956 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.5 -container-port 80
kevin 8596 2592 0 16:05 pts/1 00:00:00 grep --color=auto 8470
## http://192.168.56.101:8001/ 접속해서 확인가능하다.
## kevin@hostos1:~$ docker stats myweb1 로도 cAdvisor 처럼 볼 수 있다.
## 개발팀에게 제공받은 소스파일 옮기기 -> 실질적으로는 소스 파일 수정이다.
## 새로운 html 파일 nginx로 복사하기(scp)
kevin@hostos1:~$ mkdir LABs && cd $_
kevin@hostos1:~/LABs$ mkdir nginx-test && cd $_
kevin@hostos1:~/LABs/nginx-test$ vi index.html
# 새로운 html 적기
kevin@hostos1:~/LABs/nginx-test$ docker cp index.html myweb1:/usr/share/nginx/html/index.html
# nginx.html 파일 위치 찾기
kevin@hostos1:~/LABs/nginx-test$ sudo su -
root@hostos1:~# find / -name nginx.html
/var/lib/docker/overlay2/f9a5fa06b202c447072981a0d638bfa1171311b16ea97868c91969148e644027/diff/usr/share/nginx/html/nginx.html
/var/lib/docker/overlay2/f9a5fa06b202c447072981a0d638bfa1171311b16ea97868c91969148e644027/merged/usr/share/nginx/html/nginx.html
이제, 개발팀으로부터 개발 소스를 제공 받았다.
해당 application을 실행할 수 있는 image를 이용하여 소스와 함께 Dockerfile을 만든다. 그러면 소스 파일을 따로 넣는 작업을 하지 않아도 된다.
build time -> image 생성한다. 이 image로 docker run을 하면 소스파일들이 들어가 있는 container가 생기게 된다.
## Dockerfile 생성
kevin@hostos1:~/LABs/nginx-test$ vi 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;"]
## build 하기 - Dockerfile이 다섯줄이니까 5 step이 나온다.
kevin@hostos1:~/LABs/nginx-test$ docker build -t myweb:1.0 .
Sending build context to Docker daemon 29.7kB
Step 1/5 : FROM nginx:1.23.1-alpine
---> 804f9cebfdc5
Step 2/5 : COPY index2.html /usr/share/nginx/html/index.html
---> 299ea43f547c
Step 3/5 : COPY docker_logo.png /usr/share/nginx/html/docker_logo.png
---> 0dd40a123f70
Step 4/5 : EXPOSE 80/tcp
---> Running in 5b363f143643
Removing intermediate container 5b363f143643
---> ee49879fe1aa
Step 5/5 : CMD ["nginx", "-g", "daemon off;"]
---> Running in ddfadd3ce498
Removing intermediate container ddfadd3ce498
---> 6e7384c06f2a
Successfully built 6e7384c06f2a
Successfully tagged myweb:1.0
## image 생성되었는지 확인하기
kevin@hostos1:~/LABs/nginx-test$ docker images | grep myweb
myweb 1.0 6e7384c06f2a 35 seconds ago 23.6MB
## container 생성하기
kevin@hostos1:~/LABs/nginx-test$ docker run -d -p 8002:80 --name=myweb2 myweb:1.0
## 접속되는지 확인하기
kevin@hostos1:~/LABs/nginx-test$ curl localhost:8002
## index2.html 수정하기
kevin@hostos1:~/LABs/nginx-test$ vi index2.html
kevin@hostos1:~/LABs/nginx-test$ docker cp index2.html myweb2:/usr/share/nginx/html/index.html
kevin@hostos1:~/LABs/nginx-test$ cd
kevin@hostos1:~$ cd LABs/
kevin@hostos1:~/LABs$ mkdir stylish-portfolio && cd $_
# 소스 옮기기
kevin@hostos1:~/LABs/stylish-portfolio$ vi index.html
## Dockerfile 만들기
kevin@hostos1:~/LABs/stylish-portfolio$ vi 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;"]
## build 하기
kevin@hostos1:~/LABs/stylish-portfolio$ docker build -t myweb:2.0 .
## container 생성하기
kevin@hostos1:~/LABs/stylish-portfolio$ docker run -d -p 8003:80 --name=myweb3 myweb:2.0
## 접속되는지 확인하기
kevin@hostos1:~/LABs/stylish-portfolio$ curl localhost:8003
container best practice
1. 경량 컨테이너를 위한 image 선택은 tag에 slim, alpine이 있는 것을 권장한다.
bionic - ubuntu 18.04
focal - ubuntu 20.04