本笔记学习参考B站狂神说系列教程
什么是docker?
基于GO语言开发,开源项目,容器化技术
docker和虚拟机技术区别
- 传统虚拟机,虚拟出一套硬件,运行完整的操作系统,比如我们在虚拟机上面安装个centOS,是整套系统,然后可以在系统上安装和运行软件。
- docker容器内应用直接运行在宿主机,容器没有自己的内核,也没有虚拟的硬件,使用轻便。
- 容器之间是隔离的,容器间有各自独立的文件系统,互不影响。
应用和优势
- 快速交付和部署:
- 传统:要安装一堆环境和程序
- docker:打包镜像->发布测试->直接运行容器
- 升级与扩展:部署应用就像搭积木一样
- 简单系统运维:开发和测试环境高度一致
- 充分运用计算机资源:docker是内核级别的虚拟化,一个物理机可以运行多个容器实例
镜像(image)
- 镜像好比模板,通过镜像创建容器服务,好比从模板里创建一个实例
- 一个镜像可以创建多个容器服务
容器(container)
- 容器通过镜像创建
- 容器是独立运行的一个或者一组应用(比如我的某个容器里可以包含Tomcat或者MySQL等等服务)
- 容器好比是一个简易版系统
仓库(repository)
- 仓库是存放镜像的地方
- 分共有仓库和私有仓库
- Docker Hub(默认国外)
- 阿里云有容器服务,配置镜像加速
docker准备
- 查看系统内核
[root@VM-16-12-centos ~]# uname -r
4.18.0-305.3.1.el8.x86_64
- 查看linux系统内核版本
cat /etc/os-release
//结果
NAME="CentOS Linux"
VERSION="8 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="8"
PLATFORM_ID="platform:el8"
PRETTY_NAME="CentOS Linux 8 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:8"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"
CENTOS_MANTISBT_PROJECT="CentOS-8"
CENTOS_MANTISBT_PROJECT_VERSION="8"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="8"
-
docker安装与卸载,参考
-
配置阿里云镜像加速,参考
docker运行流程
镜像命令
docker images:查看所有本地的主机上的镜像
docker search 镜像名:搜索镜像
docker pull 镜像名 [:tag] :默认是latest,可以在tag指定下载的版本号
docker rmi 删除镜像
- docker rmi -f 容器id 删除指定的容器
- docker rmi -f 容器id 容器id …删除多个容器
- docker rmi -f $(docker images -aq) 删除全部镜像
- docker rm $(docker ps -a -q) 删除全部容器(-q)
docker commit -m=“提交描述信息” -a=“作者” 容器id 目标镜像名 :[tag] 提交容器成为一个新的副本
docker inspect 镜像名 查看镜像的元信息
容器命令
docker run [可选参数] 镜像:新建容器并启动
- 可选参数:
- –name="" 指定容器名字,用来区分容器
- -d 后台方式运行
- -it 使用交互方式运行,进入容器查看内容
- -p 指定容器的端口,如-p 8080:8080
docker ps [可选参数]<
- 可选参数:
- -a 列出当前正在运行的容器+历史运行过的容器
- -n=? 显示最近创建的容器
- -q 只显示容器的编号
exit 直接停止容器并退出
ctrl+P+Q 容器不停止退出
docker start 容器id 启动容器
docker restart 容器id 重启容器
docker stop 容器id 停止当前正在运行的容器
docker kill 容器id 强制停止当前容器
docker inspect 容器id 查看镜像的元数据
docker exec -it 容器id bashShell 进入容器
docker attach 容器id bashShell 进入容器
- 注意:docker exec是进入容器后开启一个新的终端,可以在里面操作,而docker attach 是进入正在执行的终端,不会启动新的进程
docker inspect 容器id 查看容器的源数据
docker镜像加载原理
docker的镜像实际上是由一层一层的文件系统组成,这种层级的文件系统UnionFS
boots(boot file system) 主要包bootlocader和kernel,bootloader主要是引导加载kernel,Linux刚启动时会加载bootfs文件系统,在docker镜像的最底层是bootfs,这一层与典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后,整个内核都在内存中,此时内存的使用权由bootfs转交给内核,此系统也也会卸载bootfs
在bootfs之上,包含的是典型的Linux之上,包含的是典型Linux系统中/dev,/proc,/bin,/etc等标准目录和文件,rootfs就是各种不同的操作系统的发行版。
理解:
所有的docker镜像都起始于一个基础镜像层,当进行修改或者增加新的内容时,就会在当前的镜像层之上,创建新的镜像层.
数据卷
实现容器内目录内容和宿主机目录内容同步,这可以实现持久化,当容器删除了,主机同步目录的数据还存在,主机目录也可以挂载到容器中的目录
-
方式1:docker run -it -v 主机目录:容器内目录,如
具名挂载
-v 卷名:容器内路径
[root@localhost /]# docker run -d -it --name mc1 -v mc1:/home/demo centos
89c00e60a0fd53dc7a0b6fcd5925b8bb162be2021c812608977393443f058b03
查看数据卷
[root@localhost /]# docker volume ls
DRIVER VOLUME NAME
local dfcab5d41dba19a3139e25eae0dd96d622d316c702349ce9d40ca32e64bb51a0
local f07bdd68d76d684e3260a47d6b413c52bd134ee68bd6c8a61b814673045df118
local mc1
查看某个数据卷的内容
[root@localhost /]# docker volume inspect mc1
[
{
"CreatedAt": "2022-01-23T12:02:38+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/mc1/_data",
"Name": "mc1",
"Options": null,
"Scope": "local"
}
]
匿名挂载
[root@localhost /]# docker run -it -d --name mc2 -v /home/demo centos
f4bef19013393e759ece2cbe0faf7094f2d298f067bebf5dd89613b1bfb7aa2e
数据卷容器数据同步
[root@localhost home]# docker run -d -it --name c1 -v vc1:/home/test centos
3df9d890f0e510f8a3a22f60dfcc95214622c09291c9b4639f4d329d7b612f73
[root@localhost home]# docker run -it -d --name c2 --volumes-from c1 centos
5d1b47e5ac48416dc05041ca66e91fb85084148663a52a3911e6f4f4f20e954c
[root@localhost home]# docker exec -it c2 /bin/bash //进入容器c2
[root@5d1b47e5ac48 /]# cd /home/test //在容器c2的数据卷目录下创建一个文件demo.txt
[root@5d1b47e5ac48 test]# ls
[root@5d1b47e5ac48 test]# touch demo.txt
[root@5d1b47e5ac48 test]# ls
demo.txt
[root@localhost home]# docker exec -it c1 /bin/bash //切换到容器c1
[root@3df9d890f0e5 /]# cd /home/test //进入同步数据卷目录,可以看到其中也有一个demo.txt
[root@3df9d890f0e5 test]# ls
demo.txt
经过上面的测试,我们就可以实现容器间的数据同步了
dockerfile
用途:dockerfile用来构建docker的镜像文件,是一个命令参数脚本。
构建步骤:
- 编写dockerfile文件
- docker build 构建成为镜像
- docker run 运行镜像
- docker push 发布镜像
关于构建过程:
- 每个关键字(指令)都是必须是大写字母
- 执行从上到下顺序执行
- #表示注释
- 每个指令都会重新创建提交一个新的镜像层,并提交.
dockerfile文件的指令:
指令 | 作用 |
---|---|
FROM | 基础镜像层,一切从这里开始构建 |
MAINTAINER | 镜像是谁写的,姓名+邮箱 |
RUN | 镜像构建的时候,需要运行的命令 |
ADD | 添加内容 |
WORKDIR | 镜像的工作目录 |
VOLUME | 挂载的目录 |
EXPOSE | 保留端口配置 |
CMD | 指定这个容器启动的是时候要运行的命令,只有最后一个会生效,可被替代 |
ENTRYPOINT | 指定这个容器启动的是时候要运行的命令,可追加命令 |
ONBUILD | 当构建一个被继承的dockerfile,就会执行ONBUILD的指令,触发指令 |
COPY | 将文件拷贝到镜像中 |
ENV | 在构建时设置环境变量 |
实践:构建一个自己的镜像
-
编写dockerfile
[root@localhost dockerfile]# cat dockerfile FROM centos MAINTAINER liyansheng<liyansheng0214@163.com> ENV MYPATH /usr/local WORKDIR $MYPATH RUN yum -y install vim RUN yum -y install net-tools EXPOSE 80 CMD echo $MYPATH CMD echo "---end---" CMD /bin/bash
-
构建
[root@localhost dockerfile]# docker build -f ./dockerfile -t mycentos:1.0 . Sending build context to Docker daemon 2.048kB Step 1/10 : FROM centos ---> 5d0da3dc9764 Step 2/10 : MAINTAINER liyansheng<liyansheng0214@163.com> ---> Running in 5285905d9434 Removing intermediate container 5285905d9434 ---> e79f5dd495c4 Step 3/10 : ENV MYPATH /usr/local ---> Running in 45b14e234021 Removing intermediate container 45b14e234021 ---> a2148877572e Step 4/10 : WORKDIR $MYPATH Removing intermediate container 9e48c5851ec4 ---> 05835920b703 Step 5/10 : RUN yum -y install vim (省略部分,篇幅有限,这里不展示全部)
-
查看生成的镜像
[root@localhost dockerfile]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE mycentos 1.0 00ea04d73f90 About a minute ago 326MB tomcat 9 b8e65a4d736d 4 weeks ago 680MB centos latest 5d0da3dc9764 4 months ago 231MB
docker网络
ip addr
[root@localhost /]# docker run -it -d --name m1 centos //启动一个容器
292fcdb76bb6ae98da7212eb24842c515ef58e642b750ac58b3c241b076d1346
[root@localhost /]# docker exec -it m1 ip addr //查看容器的内部地址
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
32: eth0@if33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
[root@localhost /]# ping 172.17.0.2 //外部尝试ping通容器内部的地址,经过测试发现是可以ping通的
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.095 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.045 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.076 ms
64 bytes from 172.17.0.2: icmp_seq=4 ttl=64 time=0.049 ms
64 bytes from 172.17.0.2: icmp_seq=5 ttl=64 time=0.072 ms
64 bytes from 172.17.0.2: icmp_seq=6 ttl=64 time=0.141 ms
^C
--- 172.17.0.2 ping statistics ---
6 packets transmitted, 6 received, 0% packet loss, time 4999ms
rtt min/avg/max/mdev = 0.045/0.079/0.141/0.033 ms
[root@localhost /]# docker run -it -d --name m2 centos //再启动一个容器
5df421def89457d85e462b08c65a0a10528cfa432ee8f014b9ca2aabff901e55
[root@localhost /]# docker exec -it m2 ip addr //从下我们可以知道该容器的内网连接IP是172.17.0.3
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
34: eth0@if35: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
[root@localhost /]# docker exec -it m1 /bin/bash //进入其中一个容器
[root@292fcdb76bb6 /]# ping 172.17.0.3 //尝试该容器ping另外一个容器,发现是可以ping通的
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.151 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.062 ms
64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.057 ms
64 bytes from 172.17.0.3: icmp_seq=4 ttl=64 time=0.059 ms
64 bytes from 172.17.0.3: icmp_seq=5 ttl=64 time=0.058 ms
^C
--- 172.17.0.3 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4000ms
rtt min/avg/max/mdev = 0.057/0.077/0.151/0.037 ms
查看所有的docker 网络’
[root@VM-16-12-centos /]# docker network ls
NETWORK ID NAME DRIVER SCOPE
393114baf26d bridge bridge local
76f1077c6692 host host local
abf97d86b1e6 none null local
网络模式
- bridge :桥接docker(默认)
- none:不配置网络
- host:和宿主机共享网络
- container:容器网络联通
自定义网络
[root@VM-16-12-centos /]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
098a8191cb975114dc5abe7a242ba2b8782d29c94a954cb88b3fc201a558e4d6
[root@VM-16-12-centos /]# docker network ls
NETWORK ID NAME DRIVER SCOPE
393114baf26d bridge bridge local
76f1077c6692 host host local
098a8191cb97 mynet bridge local
abf97d86b1e6 none null local
查看网络的元信息
[root@VM-16-12-centos /]# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "098a8191cb975114dc5abe7a242ba2b8782d29c94a954cb88b3fc201a558e4d6",
"Created": "2022-01-25T20:38:00.036863726+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
启动容器并指定网络
[root@VM-16-12-centos /]# docker run -it -d --name t1 --net mynet tomcat
c8bd94a5c9ba03f9f3e6877544d60c6290fafdd3dc941647a1cd488501c452e9
[root@VM-16-12-centos /]# docker run -it -d --name t2 --net mynet tomcat
fdd7f1005e76db5fc74c8ab2dc0e8416d8f71e27d331b931fddb5c3c53e84f6a
再次查看自定义网络的元信息,注意看"Containers"里面的内容,里面可以看到给容器分配的网络信息
[root@VM-16-12-centos /]# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "098a8191cb975114dc5abe7a242ba2b8782d29c94a954cb88b3fc201a558e4d6",
"Created": "2022-01-25T20:38:00.036863726+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"c8bd94a5c9ba03f9f3e6877544d60c6290fafdd3dc941647a1cd488501c452e9": {
"Name": "t1",
"EndpointID": "473830f0a14201c212f383c1a0dea9a63f67d3c97e06af451d328949e7e31d2b",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
},
"fdd7f1005e76db5fc74c8ab2dc0e8416d8f71e27d331b931fddb5c3c53e84f6a": {
"Name": "t2",
"EndpointID": "265a9e72973a7632aea69421e8ee65d4f959a69135ad16d62ed55dbce4b22968",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
将springboot项目打包成镜像
演示:
-
创建一个springboot项目
-
新建一个controller
package com.example.dockertest.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class DemoController { //返回一个字符串 @RequestMapping("demo") public String demo() { return "this is a docker demo !!!"; } }
-
启动测试,没问题
-
将项目打包
-
注意:可以先在pom.xml的文件里面指定一下用到的Java版本
<properties> <java.version>8</java.version> </properties>
-
点击按钮打包
-
打包成功后可以看到jar包
-
-
编写Dockerfile文件
FROM java:8 COPY *.jar /app.jar CMD ["--server.port=8080"] EXPOSE 8080 ENTRYPOINT ["java","-jar","/app.jar"]
-
将Dockerfile与jar包上传到Liunx(两者放到同一个目录下)
-
构建镜像
[root@VM-16-12-centos idea]# ll 总用量 17152 -rw-r--r-- 1 root root 115 1月 24 14:46 Dockerfile -rw-r--r-- 1 root root 17557203 1月 24 14:44 docker-test-0.0.1-SNAPSHOT.jar [root@VM-16-12-centos idea]# docker build -t demo1 . Sending build context to Docker daemon 17.56MB Step 1/5 : FROM java:8 8: Pulling from library/java 5040bd298390: Pull complete fce5728aad85: Pull complete 76610ec20bf5: Pull complete 60170fec2151: Pull complete e98f73de8f0d: Pull complete 11f7af24ed9c: Pull complete 49e2d6393f32: Pull complete bb9cdec9c7f3: Pull complete Digest: sha256:c1ff613e8ba25833d2e1940da0940c3824f03f802c449f3d1815a66b7f8c0e9d Status: Downloaded newer image for java:8 ---> d23bdf5b1b1b Step 2/5 : COPY *.jar /app.jar ---> ab158f3d0550 Step 3/5 : CMD ["--server.port=8080"] ---> Running in d22cd8b7b8d0 Removing intermediate container d22cd8b7b8d0 ---> bbea2dd3501b Step 4/5 : EXPOSE 8080 ---> Running in 4944ff94de47 Removing intermediate container 4944ff94de47 ---> 3efe87e95bfd Step 5/5 : ENTRYPOINT ["java","-jar","/app.jar"] ---> Running in 23292c3f2bf1 Removing intermediate container 23292c3f2bf1 ---> ccbf52061d78 Successfully built ccbf52061d78 Successfully tagged demo1:latest [root@VM-16-12-centos idea]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE demo1 latest ccbf52061d78 10 seconds ago 661MB //这个是我们构建好的镜像 tomcat latest 9f35737a8466 3 days ago 680MB hello-world latest feb5d9fea6a5 4 months ago 13.3kB centos latest 5d0da3dc9764 4 months ago 231MB java 8 d23bdf5b1b1b 5 years ago 643MB
-
通过镜像创建容器并运行,测试访问地址
[root@VM-16-12-centos ~]# docker run -it -d --name d1 -p 8081:8080 demo1 c22f3f6211e910994781b67c90adc37355af6fd1c1a6be8871d19e080895cb51 [root@VM-16-12-centos ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c22f3f6211e9 demo1 "java -jar /app.jar …" 7 seconds ago Up 6 seconds 0.0.0.0:8081->8080/tcp, :::8081->8080/tcp d1 ad6480377dd6 tomcat "catalina.sh run" 5 hours ago Up 5 hours 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp t1 5715275c3542 centos "/bin/bash" 5 hours ago Up 5 hours [root@VM-16-12-centos ~]# curl localhost:8081 {"timestamp":"2022-01-24T11:03:08.269+00:00","status":404,"error":"Not Found","path":"/"}[root@VM-16-12-centos ~]# curl localhost:8081/demo this is a docker demo !!!
从上可以看到,我们自己的容器可以运行起来,并能被外界访问了