狂神说B站视频:https://www.bilibili.com/video/BV1og4y1q7M4?p=21
Docker容器学习笔记一(狂神说Java):https://blog.csdn.net/qq_41822345/article/details/107123094
docker的理念回顾
将应用和环境打包成一个镜像!
数据?如果数据都在容器中,那么我们容器删除,数据就会丢失!需求:数据可以持久化
MySQL,容器删除了,删库跑路!需求:MySQL数据可以存储在本地!
容器之间可以有一个数据共享的技术!Docker容器中产生的数据,同步到本地!
这就是卷技术!目录的挂载,将我们容器内的目录,挂载到Linux上面!
总结一句话:容器的持久化和同步操作!容器间也是可以数据共享的!
方式一 :直接使用命令挂载 -v
-v, --volume list Bind mount a volume docker run -it -v 主机目录:容器内目录 -p 主机端口:容器内端口 ➜ ~ docker run -it -v /home/ceshi:/home centos /bin/bash #通过 docker inspect 容器id 查看 测试文件的同步再来测试!
1、停止容器
2、宿主机修改文件
3、启动容器
4、容器内的数据依旧是同步的
好处:我们以后修改只需要在本地修改即可,容器内会自动同步!
思考:MySQL的数据持久化的问题
# 获取mysql镜像 ➜ ~ docker pull mysql:5.7 # 运行容器,需要做数据挂载 #安装启动mysql,需要配置密码的,这是要注意点! # 参考官网hub docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag #启动我们得 -d 后台运行 -p 端口映射 -v 卷挂载 -e 环境配置 -- name 容器名字 ➜ ~ docker run -d -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7 # 启动成功之后,我们在本地使用sqlyog来测试一下 # sqlyog-连接到服务器的3306--和容器内的3306映射 # 在本地测试创建一个数据库,查看一下我们映射的路径是否ok!假设我们将容器删除 :
发现,我们挂载到本地的数据卷依旧没有丢失,这就实现了容器数据持久化功能。
所有的docker容器内的卷,没有指定目录的情况下都是在/var/lib/docker/volumes/xxxx/_data下 如果指定了目录,docker volume ls 是查看不到的。
# 三种挂载: 匿名挂载、具名挂载、指定路径挂载 -v 容器内路径 #匿名挂载 -v 卷名:容器内路径 #具名挂载 -v /宿主机路径:容器内路径 #指定路径挂载 docker volume ls 是查看不到的拓展:
# 通过 -v 容器内路径: ro rw 改变读写权限 ro #readonly 只读 rw #readwrite 可读可写 docker run -d -P --name nginx05 -v juming:/etc/nginx:ro nginx docker run -d -P --name nginx05 -v juming:/etc/nginx:rw nginx # ro 只要看到ro就说明这个路径只能通过宿主机来操作,容器内部是无法操作!Dockerfile 就是用来构建docker镜像的构建文件!命令脚本!先体验一下!
通过这个脚本可以生成镜像,镜像。
# 创建一个dockerfile文件,名字可以随便 建议Dockerfile # 文件中的内容 指令(大写) 参数 FROM centos VOLUME ["volume01","volume02"] CMD echo "----end----" CMD /bin/bash #这里的每个命令,就是镜像的一层!启动自己写的镜像
查看一下卷挂载
docker inspect 容器id测试一下刚才的文件是否同步出去了!
这种方式使用的十分多,因为我们通常会构建自己的镜像!
假设构建镜像时候没有挂载卷,要手动镜像挂载 -v 卷名:容器内路径!
多个MySQL同步数据!
命名的容器挂载数据卷!
--volumes-from list Mount volumes from the specified container(s) # 测试,我们通过刚才启动的测试:可以删除docker01,查看一下docker02和docker03是否可以访问这个文件
测试依旧可以访问
多个mysql实现数据共享
➜ ~ docker run -d -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7 ➜ ~ docker run -d -p 3307:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7 # 这个时候,可以实现两个容器数据同步! 结论:容器之间的配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止。
但是一旦你持久化到了本地,这个时候,本地的数据是不会删除的!
dockerfile是用来构建docker镜像的文件!命令参数脚本!
构建步骤:
1、 编写一个dockerfile文件
2、 docker build 构建称为一个镜像
3、 docker run运行镜像
4、 docker push发布镜像(DockerHub 、阿里云仓库)
但是很多官方镜像都是基础包,很多功能没有,我们通常会自己搭建自己的镜像!
官方既然可以制作镜像,那我们也可以!
基础知识:
1、每个保留关键字(指令)都是必须是大写字母
2、执行从上到下顺序
3、#表示注释
4、每一个指令都会创建提交一个新的镜像曾,并提交!
Dockerfile是面向开发的,我们以后要发布项目,做镜像,就需要编写dockerfile文件,这个文件十分简单!
Docker镜像逐渐成企业交付的标准,必须要掌握!
DockerFile:构建文件,定义了一切的步骤,源代码
DockerImages:通过DockerFile构建生成的镜像,最终发布和运行产品。
Docker容器:容器就是镜像运行起来提供服务。
# DockerFile常用指令 FROM # 基础镜像,一切从这里开始构建 MAINTAINER # 镜像是谁写的, 姓名+邮箱 RUN # 镜像构建的时候需要运行的命令 ADD # 步骤,tomcat镜像,这个tomcat压缩包!添加内容 添加同目录 WORKDIR # 镜像的工作目录 VOLUME # 挂载的目录 EXPOSE # 保留端口配置 CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代。 ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令 ONBUILD # 当构建一个被继承 DockerFile 这个时候就会运行ONBUILD的指令,触发指令。 COPY # 类似ADD,将我们文件拷贝到镜像中 ENV # 构建的时候设置环境变量!创建一个自己的centos
# 1.编写Dockerfile文件 vim mydockerfile-centos FROM centos MAINTAINER cheng<1204598429@qq.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 # 2、通过这个文件构建镜像 # 命令 docker build -f 文件路径 -t 镜像名:[tag] . docker build -f mydockerfile-centos -t mycentos:0.1 .测试运行
我们可以列出本地进行的变更历史
CMD 和 ENTRYPOINT区别
CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代。 ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令测试cmd
# 编写dockerfile文件 $ vim dockerfile-test-cmd FROM centos CMD ["ls","-a"] # 构建镜像 $ docker build -f dockerfile-test-cmd -t cmd-test:0.1 . # 运行镜像 $ docker run cmd-test:0.1 . .. .dockerenv bin dev # 想追加一个命令 -l 成为ls -al $ docker run cmd-test:0.1 -l docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"-l\": executable file not found in $PATH": unknown. ERRO[0000] error waiting for container: context canceled # cmd的情况下 -l 替换了CMD["ls","-l"]。 -l 不是命令所有报错测试ENTRYPOINT
# 编写dockerfile文件 $ vim dockerfile-test-entrypoint FROM centos ENTRYPOINT ["ls","-a"] $ docker run entrypoint-test:0.1 . .. .dockerenv bin dev etc home lib lib64 lost+found ... # 我们的命令,是直接拼接在我们得ENTRYPOINT命令后面的 $ docker run entrypoint-test:0.1 -l total 56 drwxr-xr-x 1 root root 4096 May 16 06:32 . drwxr-xr-x 1 root root 4096 May 16 06:32 .. -rwxr-xr-x 1 root root 0 May 16 06:32 .dockerenv lrwxrwxrwx 1 root root 7 May 11 2019 bin -> usr/bin drwxr-xr-x 5 root root 340 May 16 06:32 dev drwxr-xr-x 1 root root 4096 May 16 06:32 etc drwxr-xr-x 2 root root 4096 May 11 2019 home lrwxrwxrwx 1 root root 7 May 11 2019 lib -> usr/lib lrwxrwxrwx 1 root root 9 May 11 2019 lib64 -> usr/lib64 ....Dockerfile中很多命令都十分的相似,我们需要了解它们的区别,我们最好的学习就是对比他们然后测试效果!
1、准备镜像文件
准备tomcat 和 jdk到当前目录,编写好README 。
2、编写dokerfile
FROM centos # MAINTAINER cheng<1204598429@qq.com> COPY README /usr/local/README #复制文件 ADD jdk-8u231-linux-x64.tar.gz /usr/local/ #复制解压 ADD apache-tomcat-9.0.35.tar.gz /usr/local/ #复制解压 RUN yum -y install vim ENV MYPATH /usr/local #设置环境变量 WORKDIR $MYPATH #设置工作目录 ENV JAVA_HOME /usr/local/jdk1.8.0_231 #设置环境变量 ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.35 #设置环境变量 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib #设置环境变量 分隔符是: EXPOSE 8080 #设置暴露的端口 CMD /usr/local/apache-tomcat-9.0.35/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.35/logs/catalina.out # 设置默认命令3、构建镜像
# 因为dockerfile命名使用默认命名 因此不用使用-f 指定文件 $ docker build -t mytomcat:0.1 .4、run镜像
$ docker run -d -p 8080:8080 --name tomcat01 -v /home/kuangshen/build/tomcat/test:/usr/local/apache-tomcat-9.0.35/webapps/test -v /home/kuangshen/build/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.35/logs mytomcat:0.15、访问测试
6、发布项目(由于做了卷挂载,我们直接在本地编写项目就可以发布了!)
发现:项目部署成功,可以直接访问!
我们以后开发的步骤:需要掌握Dockerfile的编写!我们之后的一切都是使用docker镜像来发布运行!
1、地址 https://hub.docker.com/
2、确定这个账号可以登录
3、登录
$ docker login --help Usage: docker login [OPTIONS] [SERVER] Log in to a Docker registry. If no server is specified, the default is defined by the daemon. Options: -p, --password string Password --password-stdin Take the password from stdin -u, --username string Username4、提交 push镜像
# 会发现push不上去,因为如果没有前缀的话默认是push到 官方的library # 解决方法 # 第一种 build的时候添加你的dockerhub用户名,然后在push就可以放到自己的仓库了 $ docker build -t chengcoder/mytomcat:0.1 . # 第二种 使用docker tag #然后再次push $ docker tag 容器id chengcoder/mytomcat:1.0 #然后再次push阿里云镜像服务上
看官网 很详细https://cr.console.aliyun.com/repository/
$ sudo docker login --username=zchengx registry.cn-shenzhen.aliyuncs.com $ sudo docker tag [ImageId] registry.cn-shenzhen.aliyuncs.com/dsadxzc/cheng:[镜像版本号] # 修改id 和 版本 sudo docker tag a5ef1f32aaae registry.cn-shenzhen.aliyuncs.com/dsadxzc/cheng:1.0 # 修改版本 $ sudo docker push registry.cn-shenzhen.aliyuncs.com/dsadxzc/cheng:[镜像版本号]清空所有网络
三个网络
问题: docker 是如果处理容器网络访问的?
# 测试 运行一个tomcat $ docker run -d --name tomcat01 tomcat $ 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 inet6 ::1/128 scope host valid_lft forever preferred_lft forever 551: vethbfc37e3@if550: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default link/ether 1a:81:06:13:ec:a1 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet6 fe80::1881:6ff:fe13:eca1/64 scope link valid_lft forever preferred_lft forever $ docker exec -it 容器id $ ip addr # 查看容器内部网络地址 发现容器启动的时候会得到一个 eth0@if551 ip地址,docker分配! 550: eth0@if551: <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 # 思考? linux能不能ping通容器内部! 可以 容器内部可以ping通外界吗? 可以! $ ping 172.17.0.2 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.069 ms 64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.074 ms原理
1、我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要按照了docker,就会有一个docker0桥接模式,使用的技术是veth-pair技术! https://www.cnblogs.com/bakari/p/10613710.html 再次测试ip add
2 、在启动一个容器测试,发现又多了一对网络
我们发现这个容器带来网卡,都是一对对的 veth-pair 就是一对的虚拟设备接口,他们都是成对出现的,一端连着协议,一端彼此相连 正因为有这个特性 veth-pair 充当一个桥梁,连接各种虚拟网络设备的 OpenStac,Docker容器之间的连接,OVS的连接,都是使用evth-pair技术
3、我们来测试下tomcat01和tomcat02是否可以ping通
$ docker-tomcat docker exec -it tomcat01 ip addr #获取tomcat01的ip 172.17.0.2 550: eth0@if551: <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 $ docker-tomcat docker exec -it tomcat02 ping 172.17.0.2#让tomcat02ping tomcat01 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.098 ms 64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.071 ms # 可以ping通结论:tomcat01和tomcat02公用一个路由器,docker0。
所有的容器不指定网络的情况下,都是docker0路由的,docker会给我们的容器分配一个默认的可用ip。
小结: Docker使用的是Linux的桥接,宿主机是一个Docker容器的网桥 docker0
Docker中所有网络接口都是虚拟的,虚拟的转发效率高(内网传递文件)
只要容器删除,对应的网桥一对就没了!
思考一个场景:我们编写了一个微服务,database url=ip: 项目不重启,数据ip换了,我们希望可以处理这个问题,可以通过名字来进行访问容器?探究: docker network inspect 网络id 网段相同
docker inspect tomcat03
查看tomcat03里面的/etc/hosts发现有tomcat02的配置
–link 本质就是在hosts配置中添加映射
现在使用Docker已经不建议使用–link了!
自定义网络,不适用docker0!
docker0问题:不支持容器名连接访问!
网络模式
bridge :桥接 docker(默认,自己创建也是用bridge模式)
none :不配置网络,一般不用
host :和所主机共享网络
container :容器网络连通(用得少!局限很大)
测试
# 我们直接启动的命令 --net bridge,而这个就是我们得docker0 # bridge就是docker0 $ docker run -d -P --name tomcat01 tomcat 等价于 => docker run -d -P --name tomcat01 --net bridge tomcat # docker0,特点:默认,域名不能访问。 --link可以打通连接,但是很麻烦! # 我们可以 自定义一个网络 $ docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet $ docker network inspect mynet;启动两个tomcat,再次查看网络情况
在自定义的网络下,服务可以互相ping通,不用使用–link
我们自定义的网络docker当我们维护好了对应的关系,推荐我们平时这样使用网络!
好处:
redis -不同的集群使用不同的网络,保证集群是安全和健康的
mysql-不同的集群使用不同的网络,保证集群是安全和健康的
# 测试两个不同的网络连通 再启动两个tomcat 使用默认网络,即docker0 $ docker run -d -P --name tomcat01 tomcat $ docker run -d -P --name tomcat02 tomcat # 此时ping不通
要将tomcat01 连通 tomcat—net-01 ,连通就是将 tomcat01加到 mynet网络
一个容器两个ip(tomcat01) 01连通 ,加入后此时,已经可以tomcat01 和 tomcat-01-net ping通了
02是依旧不通的
结论:假设要跨网络操作别人,就需要使用docker network connect 连通!
docker搭建redis集群完成!
我们使用docker之后,所有的技术都会慢慢变得简单起来!
1、构建SpringBoot项目
2、打包运行
mvn package3、编写dockerfile
FROM java:8 COPY *.jar /app.jar CMD ["--server.port=8080"] EXPOSE 8080 ENTRYPOINT ["java","-jar","app.jar"]4、构建镜像
# 1.复制jar和DockerFIle到服务器 # 2.构建镜像 $ docker build -t xxxxx:xx .5、发布运行
以后我们使用了Docker之后,给别人交付就是一个镜像即可!
Docker定义:Docker 是一个开源的应用容器引擎,它可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制( 沙箱是一个虚拟系统程序,沙箱提供的环境相对于每一个运行的程序都是独立的,而且不会对现有的系统产生影响 ),相互之间不会有任何接口,更重要的是容器性能开销极低。
Docker的优点
Docker 是一个用于开发,交付和运行应用程序的开放平台。Docker 使您能够将应用程序与基础架构分开,从而可以快速交付软件。借助 Docker,您可以与管理应用程序相同的方式来管理基础架构。通过利用 Docker 的方法来快速交付,测试和部署代码,您可以大大减少编写代码和在生产环境中运行代码之间的延迟。
Docker应用场景
Web 应用的自动化打包和发布。
自动化测试和持续集成、发布。在服务型环境中部署和调整数据库或其他的后台应用。从头编译或者扩展现有的 OpenShift 或 Cloud Foundry 平台来搭建自己的 PaaS 环境。我们用的传统虚拟机如 VMware之类的需要模拟整台机器包括硬件,每台虚拟机都需要有自己的操作系统,虚拟机一旦被开启,预分配给它的资源将全部被占用。每一台虚拟机包括应用,必要的二进制和库,以及一个完整的用户操作系统。
而容器技术是和我们的宿主机共享硬件资源及操作系统,可以实现资源的动态分配。容器包含应用和其所有的依赖包,但是与其他容器共享内核。容器在宿主机操作系统中,在用户空间以分离的进程运行。
容器技术是实现操作系统虚拟化的一种途径,可以让您在资源受到隔离的进程中运行应用程序及其依赖关系。通过使用容器,我们可以轻松打包应用程序的代码、配置和依赖关系,将其变成容易使用的构建块,从而实现环境一致性、运营效率、开发人员生产力和版本控制等诸多目标。容器可以帮助保证应用程序快速、可靠、一致地部署,其间不受部署环境的影响。容器还赋予我们对资源更多的精细化控制能力,让我们的基础设施效率更高。
**Docker 属于 Linux 容器的一种封装,提供简单易用的容器使用接口。**它是目前最流行的 Linux容器解决方案。
Docker 将应用程序与该程序的依赖,打包在一个文件里面。运行这个文件,就会生成一个虚拟容器。程序在这个虚拟容器里运行,就好像在真实的物理机上运行一样。有了 Docker ,就不用担心环境问题。
总体来说, Docker 的接口相当简单,用户可以方便地创建和使用容器,把自己的应用放入容器。容器还可以进行版本管理、复制、分享、修改,就像管理普通的代码一样。
Docker的几个重要概念,如下图所示:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XeqFsp8V-1593846155510)(C:\Users\Administrator\Desktop\我的文档\photo\Docker.png)]
镜像就类似于在创建虚拟机前需要下载的系统镜像文件,比如iso文件、img文件等一些镜像文件。
镜像是 Docker 运行容器的前提,仓库是存放镜像的场所,可见镜像更是Docker的核心。
容器可以类比于正在运行中的虚拟机。
你可以将你的镜像save为一个tar文件,别人就可以通过load来获取你的镜像。
仓库中则保存了很多公共的常用的镜像,比如常用的JDK镜像、MySQL镜像、tomcat镜像、Ubuntu镜像、ngnix镜像等等。你可以通过pull来拉取获得这些镜像,你也可以自定义一些镜像通过push推送到仓库中。
Dockerfile就是一个build镜像的文件,它描述并指定了应该如何构建一个镜像。
Dockerfile 是自动构建 docker 镜像的配置文件, 用户可以使用 Dockerfile 快速创建自定义的镜像。Dockerfile 中的命令非常类似于 linux 下的 shell 命令。 一般来说,我们可以将 Dockerfile 分为四个部分:
基础镜像(父镜像)信息指令 FROM维护者信息指令 MAINTAINER镜像操作指令 RUN 、 EVN 、 ADD 和 WORKDIR 等容器启动指令 CMD 、 ENTRYPOINT 和 USER 等1.Docker 容器使用 获取镜像 启动容器 查看容器 启动已经停止的容器 后台运行 停止一个容器 进入容器 退出容器 导出容器 导入容器 容器快照 删除容器 清理掉所有处于终止状态的容器
2.Docker Web应用 运行一个web应用 以端口5000开启端口 关闭web应用 重启web应用 移除web应用
3.Docker 镜像应用 列出镜像列表 获取镜像
4.Dockerfile 构建镜像
step1:添加Docker的maven的插件,配置Dockerfile的path;
<!-- Docker maven plugin --> <plugin> <groupId>com.spotify</groupId> <artifactId>docker-maven-plugin</artifactId> <version>0.4.13</version> <configuration> <imageName>${docker.image.prefix}/${project.artifactId}</imageName> <dockerDirectory>${project.basedir}/src/main/docker</dockerDirectory> <resources> <resource> <targetPath>/</targetPath> <directory>${project.build.directory}</directory> <include>${project.build.finalName}.jar</include> </resource> </resources> </configuration> </plugin>step2:在配置的Dockerfile的path处添加Dockerfile文件;
Step3:文件中添加配置:
FROM openjdk:8-jdk-alpine VOLUME /tmp #把当前项目下dockertest-0.0.1-SNAPSHOT.jar 改名为test.jar 添加到镜像中 ADD web-app-template-1.0.0.jar test.jar #指定端口,最好写与项目配置的端口 EXPOSE 8080 #在镜像中运行/test.jar包,这样在运行镜像的时候就已经启动好了test.jar ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/test.jar"]Step4:mvn clean package -Dmaven.test.skip=true (表示不执行测试用例,也不编译测试用例类。)
step5:mvn package docker:build 打镜像
step6:docker images 查看镜像
step7:docker run -p 8081:8081 -t springboot/web-app-template 运行
step8:查看运行结果:http://localhost:8081/…
step9:docker push