关于docker的学习与实践

What is Docker

简单来说,docker是一款容器。一台电脑可以有多个docker环境,这些多个docker环境共享使用电脑的CPU,内存和硬盘等。

docker的组成,总共有3大部分。

  1. Docker主机
    • 服务器: 获取镜像,并运行出对应的容器
      • 容器 Container: 我们的应用程序就运行在这里
      • 镜像 image: 用于构建容器,应用程序所需的运行环境,打包为镜像文件
  2. 客户端
    • Docker构建: 基于dockerfile构建镜像
      • Dockerfile的作用: 将我们部署项目的操作,写成一个部署脚本,这个脚本就是dockerfile,且该脚本还能够构建出镜像文件。
    • Docker拉取: 下载别人的docker镜像,用docker pull指令
    • Dokcer启动: 启动docker容器
  3. 镜像仓库
    • 在网络中的一个仓库,用于管理docker的镜像image,运行image生成容器
    • dockerhub,好比github
    • 仓库中有UBUNTU,NGINX等镜像文件

Install

Run

docker run [parameter] [image_name/ID]

1
docker run -d -p 80:80 nginx

-d 后台运行容器,不会占用前台
-p 80:80 端口映射,宿主机端口:容器内端口,访问宿主机的这个端口也就访问到了容器内的这个端口

1
docker run -d -p 80:80 nginx

查看容器是否在运行

1
2
3
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
014732a965e9 nginx "/docker-entrypoint.…" About a minute ago Up About a minute 0.0.0.0:80->80/tcp, :::80->80/tcp wonderful_snyder

访问宿主机的80端口
ifconfig确认IP地址
192.168.10.115:80
确认宿主机80端口是否存在

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
zhi@thinkpad:~$ sudo netstat -tunlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN 779/systemd-resolve
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN 648871/cupsd
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 663134/docker-proxy
tcp 0 0 0.0.0.0:139 0.0.0.0:* LISTEN 2008/smbd
tcp 0 0 0.0.0.0:445 0.0.0.0:* LISTEN 2008/smbd
tcp 0 0 127.0.0.1:37083 0.0.0.0:* LISTEN 655906/code
tcp 0 0 127.0.0.1:8000 0.0.0.0:* LISTEN 1056/daemon
tcp6 0 0 ::1:631 :::* LISTEN 648871/cupsd
tcp6 0 0 :::80 :::* LISTEN 663140/docker-proxy
tcp6 0 0 :::139 :::* LISTEN 2008/smbd
tcp6 0 0 :::445 :::* LISTEN 2008/smbd
udp 0 0 127.0.0.53:53 0.0.0.0:* 779/systemd-resolve
udp 0 0 192.168.10.255:137 0.0.0.0:* 1978/nmbd
udp 0 0 192.168.10.115:137 0.0.0.0:* 1978/nmbd
udp 0 0 172.17.255.255:137 0.0.0.0:* 1978/nmbd
udp 0 0 172.17.0.1:137 0.0.0.0:* 1978/nmbd
udp 0 0 0.0.0.0:137 0.0.0.0:* 1978/nmbd
udp 0 0 192.168.10.255:138 0.0.0.0:* 1978/nmbd
udp 0 0 192.168.10.115:138 0.0.0.0:* 1978/nmbd
udp 0 0 172.17.255.255:138 0.0.0.0:* 1978/nmbd
udp 0 0 172.17.0.1:138 0.0.0.0:* 1978/nmbd
udp 0 0 0.0.0.0:138 0.0.0.0:* 1978/nmbd
udp 0 0 127.0.0.1:323 0.0.0.0:* 1156/chronyd
udp 0 0 0.0.0.0:631 0.0.0.0:* 648872/cups-browsed
udp 0 0 0.0.0.0:33584 0.0.0.0:* 280757/chrome --typ
udp 0 0 0.0.0.0:50605 0.0.0.0:* 280757/chrome --typ
udp 0 0 0.0.0.0:53815 0.0.0.0:* 999/avahi-daemon: r
udp 0 0 224.0.0.251:5353 0.0.0.0:* 280712/chrome --ena
udp 0 0 224.0.0.251:5353 0.0.0.0:* 280712/chrome --ena
udp 0 0 224.0.0.251:5353 0.0.0.0:* 280757/chrome --typ
udp 0 0 0.0.0.0:5353 0.0.0.0:* 999/avahi-daemon: r
udp6 0 0 :::60900 :::* 280757/chrome --typ
udp6 0 0 ::1:323 :::* 1156/chronyd
udp6 0 0 fe80::9ec8:9d94:e16:546 :::* 1013/NetworkManager
udp6 0 0 :::51236 :::* 280757/chrome --typ
udp6 0 0 :::35795 :::* 999/avahi-daemon: r
udp6 0 0 :::5353 :::* 999/avahi-daemon: r

停止容器

1
2
3
4
5
6
7
8
zhi@thinkpad:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
014732a965e9 nginx "/docker-entrypoint.…" 10 minutes ago Up 10 minutes 0.0.0.0:80->80/tcp, :::80->80/tcp wonderful_snyder
zhi@thinkpad:~$ docker stop 014732a965e9
014732a965e9
zhi@thinkpad:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
zhi@thinkpad:~$

此时已经无法访问192.168.10.115:80
重新启动

1
docker start 014732a965e9

执行之后又可以正常访问80端口了,这样就实现了快速启停。

Docker的生命周期

Docker的镜像原理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
zhi@thinkpad:~$ docker pull redis
Using default tag: latest
latest: Pulling from library/redis
31b3f1ad4ce1: Already exists
ff29a33e56fb: Pull complete
b230e0fd0bf5: Pull complete
7fe3ad196642: Pull complete
3d8096d6920c: Pull complete
85e4b89053d8: Pull complete
Digest: sha256:091a7b5de688f283b30a4942280b64cf822bbdab0abfb2d2ce6db989f2d3c3f4
Status: Downloaded newer image for redis:latest
docker.io/library/redis:latest
zhi@thinkpad:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
redis latest 2460522297a1 5 days ago 117MB
nginx latest 2d389e545974 5 days ago 142MB
slepp/arduino latest 5e10cf71a843 4 years ago 893MB

在获取redis的时候,下载了5行信息,最终得到了一特完整的镜像文件。
查看系统的2大部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 zhi@thinkpad:~$ cat /etc/os-release 
NAME="Ubuntu"
VERSION="20.04.4 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.4 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal
zhi@thinkpad:~$ uname -r
5.15.0-46-generic
zhi@thinkpad:~$

如果想灵活的替换发行版OS,要怎么办?这种时候需要Docker。
内核都共用宿主机的内核,只替换上层的发行版。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
zhi@thinkpad:~$ docker pull centos:7.8.2003
7.8.2003: Pulling from library/centos
9b4ebb48de8d: Pull complete
Digest: sha256:8540a199ad51c6b7b51492fa9fee27549fd11b3bb913e888ab2ccf77cbb72cc1
Status: Downloaded newer image for centos:7.8.2003
docker.io/library/centos:7.8.2003
zhi@thinkpad:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
redis latest 2460522297a1 5 days ago 117MB
nginx latest 2d389e545974 5 days ago 142MB
centos 7.8.2003 afb6fca791e0 2 years ago 203MB
slepp/arduino latest 5e10cf71a843 4 years ago 893MB
#运行容器且进入容器内
-i 交互式命令操作。我执行ls命令后可以立即返回一个结果
-t 开启一个终端
bash 进入容器后,执行的命令。ls等的命令都是通过bash来执行的
zhi@thinkpad:~$ docker run -it afb6fca791e0 bash
[root@603a1d5e03d1 /]# ls
anaconda-post.log dev home lib64 mnt proc run srv tmp var
bin etc lib media opt root sbin sys usr
[root@603a1d5e03d1 /]# cat /etc/redhat-release
CentOS Linux release 7.8.2003 (Core)
[root@603a1d5e03d1 /]# uname -r
5.15.0-46-generic
[root@603a1d5e03d1 /]# exit
exitdo

通过上面的信息可以确认到使用了Centos的发行版和宿主机的内核。