- Docker概述
- Docker为什么出现
- Docker历史
- Docker能干什么
- Docker架构图
- 安装Docker
- 安装准备
- 安装
- 阿里云镜像加速
- 回顾helloworld流程
- Docker底层原理
- Docker的常用命令
- 帮助命令
- 镜像命令
- 容器命令
- 其他常用命令
- 小结
- 作业
- 部署nginx
- 部署tomcat
- 可视化工具portainer
- 镜像讲解
- Docker镜像加载原理
- 分层理解
- commit镜像
- 实战测试
- 容器数据卷
- 什么是容器数据卷
- 使用数据卷
- mysql实战 *** 作
- 具名挂载和匿名挂载
- 匿名挂载 -v 容器内路径
- 具名挂载
- 如何确定是具名挂载还是匿名挂载,还是指定路径挂载
- 拓展
- 初始dockerfile
- 数据卷同步
- 数据卷容器
- dockerfile
- dockerfile搭建过程
- 基础知识
- dockerfile指令
- 实战测试
- CMD和ENTRYPOINT的区别
- tomcat实战
- 发布自己的镜像
- 发布自己的镜像
- 发布到阿里云
- docker网络
- 理解docker网络
- –link(不适用当前)
- 自定义网络(容器互联)
- 网络连通
- 实战:部署Redis集群
- Springboot微服务打包Docker镜像
- 其他
参考【狂神说Java】Docker最新超详细版教程通俗易懂
Docker概述 Docker为什么出现一款产品:开发-上线两套环境!应用环境,应用配置!
开发—运维。问题:我在我的电脑上可以运行!版本更新,导致服务不可用!对于运维来说,考验就十分大?
环境配置是十分的麻烦,每一个机器都要部署环境(集群Redis、ES、Hadoop.…)!费时费力。
发布一个项目(jar+(Redis MySQL jdkES)),项目能不能都带上环境安装打包!
之前在服务器配置一个应用的环境Redis MySQL jdk ES Hadoop,配置超麻烦了,不能够跨平台。
Windows,最后发布到Linux!
传统:开发jar,运维来做!
现在:开发打包部署上线,一套流程做完!
java–apk–发布(应用商店)—张三使用apk—安装即可用!
java–jar(环境)—打包项目带上环境(镜像)—(Docker仓库:商店)—下载我们发布的镜像–直接运行即可!
Docker的思想就来自于集装箱!
JRE–多个应用(端囗冲突)–原来都是交叉的!
隔离:Docker核心思想!打包装箱!每个箱子是互相隔离的。
Docker通过隔离机制,可以将服务器利用到极致!
2010年,几个搞IT的年轻人,就在美国成立了一家公司dotcloud做一些pass的云计算服务!LXC有关的容器技术!
他们将自己的技术(容器化技术)命名就是Docker!
Docker刚刚诞生的时候,没有引起行业的注意!dotCloud,就活不下去开源开发源代码!2013年,Docker开源!Docker越来越多的人发现了docker的优点!火了,Docker每个月都会更新一个版本!2014年4月9日,Docker1.0发布!
Docker为什么这么火?十分的轻巧!
在容器技术出来之前,我们都是使用虚拟机技术!
虚拟机:在window中装一个Vmware,通过这个软件我们可以虚拟出来一台或者多台电脑!笨重!
在容器技术出来之前,我们都是使用虚拟机技术!
虚拟机:在window中装一个Vmware,通过这个软件我们可以虚拟出来一台或者多台电脑!笨重!虚拟机也是属于虚拟化技术,Docker容器技术,也是一种虚拟化技术!
vmware linux centos原生镜像,相当于一个虚拟电脑 可以实现隔离,开多个虚拟机 占用内存几个G 启动时间几分钟 docker 可以隔离,是(最核心的环境 + jdk + mysql) 很小 几个M 运行时间秒级
Docker 基于go语言开发
之前的虚拟机技术
虚拟机技术缺点
1、资源占用十分多
2、冗余步骤多
3、启动慢
容器化技术不是模拟一个完整的 *** 作系统
比较Docker和虚拟机技术的不同:
- 传统虚拟机,虚拟出一套硬件,运行一个完整的 *** 作系统,然后在这个系统上安装和运行软件
- 容器内的应用直接运行在宿主机的内容,容器是没有自己的内核的,也没有虚拟我们的硬件,所以就轻便了
- 每个容器间是互相隔离,每个容器内都有一个属于自己的文件系统,互不影响。
容器化技术的优点
- 应用更快速的交付和部署
传统:一堆帮助文档,安装程序
Docker:打包镜像发布测试,一键运行 - 更便捷的升级和扩缩容
使用了Docker之后,我们部署应用就和搭积木一样!
项目打包为一个镜像,扩展服务器A!服务器B - 更简单的系统运维
在容器化之后,我们的开发,测试环境都是高度一致的。 - 更高效的计算资源利用:
Docker是内核级别的虚拟化,可以再一个物理机上可以运行很多的容器实例!服务器的性能可以被压榨到极致。
Linux要求内核3.0以上
# 查看内核 [root@localhost ~]# uname -r 3.10.0-1160.el7.x86_64 # 查看配置 [root@localhost ~]# cat /etc/os-release NAME="CentOS Linux" VERSION="7 (Core)" ID="centos" ID_LIKE="rhel fedora" VERSION_ID="7" PRETTY_NAME="CentOS Linux 7 (Core)" ANSI_COLOR="0;31" CPE_NAME="cpe:/o:centos:centos:7" HOME_URL="https://www.centos.org/" BUG_REPORT_URL="https://bugs.centos.org/" CENTOS_MANTISBT_PROJECT="CentOS-7" CENTOS_MANTISBT_PROJECT_VERSION="7" REDHAT_SUPPORT_PRODUCT="centos" REDHAT_SUPPORT_PRODUCT_VERSION="7"安装
帮助文档:https://docs.docker.com/engine/install/
#1.卸载旧版本 yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine #2.需要的安装包 yum install -y yum-utils #3.设置镜像的仓库 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo #默认是从国外的,不推荐 #推荐使用国内的 yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo #更新yum软件包索引 yum makecache fast #4.安装docker相关的 docker-ce 社区版 而ee是企业版 yum install docker-ce docker-ce-cli containerd.io #5、启动docker systemctl start docker #6. 使用docker version查看是否安装成功 docker version #7. 测试 docker run hello-world
#7. 测试 [root@localhost ~]# docker run hello-world Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker ID: https://hub.docker.com/ For more examples and ideas, visit: https://docs.docker.com/get-started/
# 8.查看一下下载的镜像 [root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest d1165f221234 3 months ago 13.3kB
了解:卸载docker
#1. 卸载依赖 yum remove docker-ce docker-ce-cli containerd.io #2. 删除资源 rm -rf /var/lib/docker # /var/lib/docker 是docker的默认工作路径!阿里云镜像加速
1、登录阿里云找到容器服务
https://cr.console.aliyun.com/cn-shenzhen/instances/mirrors
2、配置使用
docker是怎么工作的?
Docker是一个Client-Server结构的服务器,Docker的守护进程运行在主机上,通过Socket从客户端访问!Docker-Server接收到Docker-Client指令,就会执行这个命令。
docker为什么比VM快?
1、Docker有着比虚拟机更少的抽象层
2、docker利用的是宿主机的内核,vm需要是Guest os
所以说,新建一个容器的时候,docker不需要想虚拟机一样重新加载一个 *** 作系统内核,避免引导。虚拟机是加载 GuestOS,分钟级别的,而docker是利用宿主机的 *** 作系统吗,省略了这个复杂的过程,秒级!
docker version #查看docker版本信息 docker info #显示docker系统信息,包括镜像和容器的数量 docker xxx --help #帮助命令
帮助文档:https://docs.docker.com/reference/
https://docs.docker.com/engine/reference/commandline/docker/
https://docs.docker.com/engine/reference/commandline/images/
查看镜像
docker images 查看所有本地主机上的镜像 REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest d1165f221234 4 months ago 13.3kB 镜像的仓库源 标签 镜像ID 镜像创建时间 镜像大小
帮助命令
使用docker images --help 查看images参数命令 常见参数 -a :列出本地所有镜像 -q :只列出镜像ID –digests :显示镜像的摘要信息 –no trunc :显示完整的镜像信息 -s :列出收藏数不小于指定值的镜像
在仓库中搜索镜像
docker search 搜索镜像 #过滤docker search 中的信息 docker search tomcat --filter=STARS=3000 过滤收藏大于3000的tomcat镜像 docker search mysql
下载镜像
docker pull 下载镜像 docker pull 镜像名[:tag],如果不写tag,默认是latest docker pull mysql //等价于docker pull mysql.io/library/mysql:latest docker pull mysql:5.7 //下载mysql指定的版本5.7,版本在docker官网中必须有。 docker pull tomcat:9 9: Pulling from library/tomcat //如果不写tag,默认就是latest d960726af2be: Pull complete //分层下载: docker image 的核心 联合文件系统 e8d62473a22d: Pull complete Digest: sha256:71703331e3e7f8581f2a8206a612dbeedfbc7bb8caeee972eadca1cc4a72e6b1 // 签名 防伪 Status: Downloaded newer image for tomcat:9 docker.io/library/tomcat:9 //真实地址 #等价于 docker pull tomcat:9 docker pull docker.io/library/tomcat:9
删除镜像
docker rmi -f 镜像id #删除指定的镜像 docker rmi -f 镜像id 镜像id 镜像id 镜像id #删除指定的镜像 docker rmi -f $(docker images -aq) #删除全部的镜像 $(docker images -aq) 表示取 docker images -aq 得到的内容作为参数 docker rm 是删除容器
其他
docker history 镜像id 查看镜像的构建命令容器命令
说明:我们有了镜像才可以创建容器,linux,下载一个centos镜像测试学习
先下载一个centos虚拟机
docker pull centos
docker run 在新容器中运行命令,该docker run命令首先creates在指定映像上创建一个可写容器层,然后starts使用指定的命令
运行容器镜像
docker run [可选参数] [image镜像] #参数说明 --name="Name" //Name是容器名字,如tomcat01,tomcat02 -d //后台方式运行 -it //使用交互式运行,进入容器查看内容 -p //指定容器端口 -p 8080:8080 -p ip:主机端口:容器端口 -p 主机端口:容器端口(常用) -p 容器端口 -P //随机指定端口
测试
[root@localhost ~]# docker run -it centos /bin/bash #在指定镜像上创建一个可写容器层 -it 表示交互 *** 作 centos /bin/bash 表示交互控制台 [root@21b5801833c3 /]# ls bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var # 后台运行tomcat,-p 表示是把需拟机的8888端口映射到容器中的8080端口 [root@localhost /]# docker run -d -p 8888:8080 c43a65faae57 f0119f0207f3f5f5db72 [root@localhost /]# docker ps 查看运行中的容器 ConTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f0119f0207f3 c43a65faae57 "catalina.sh run" 16 minutes ago Up 16 minutes 0.0.0.0:8888->8080/tcp, :::8888->8080/tcp trusting_shannon # 启动并进入容器 # [root@localhost /]# docker run -it c43a65faae57 /bin/bash # 进入已启动容器 [root@localhost /]# docker exec -it f0119f0207f3 /bin/bash [root@aabc66e4ef0d:/]# ls BUILDING.txt LICENSE README.md RUNNING.txt conf logs temp webapps.dist CONTRIBUTING.md NOTICE RELEASE-NOTES bin lib native-jni-lib webapps work #从容器退回主机 [root@aabc66e4ef0d:/]# exit exit
列出所有运行的容器
docker ps [参数] -a, --all #列出当前正在运行的容器 + 带出历史运行过的容器 -n, --last int -n=? #?指历史记录,1表示-a的第一列,以此类推 -q, --quiet #只显示容器id
启动和停止容器
docker start 容器id #启动容器 docker restart 容器id #重启容器 docker stop 容器id #停止当前正在运行的容器 docker kill 容器id #强制停止当前容器
退出容器
exit #容器直接退出 ctrl + P + Q #容器不停止退出
删除容器
docker rm 容器id #删除指定的容器,不能删除正在运行的容器 docker rm -rf 容器id #强制删除,可以删除正在运行的容器 docker rm -f $(docker ps -aq) #删除所有运行中和历史的容器,会删除正在运行的容器 docker ps -a -q|xargs docker rm #删除所有的容器其他常用命令
[root@localhost /]# docker run -d centos -d表示后台启动容器 6f114cdff4d934d0a2f005baeaeb86f [root@localhost /]# docker ps ConTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES # 后台启动centos,docker ps 发现centos 停止了 # 原因: docker容器使用后台运行,必须有一个前台的进程,docker发现没有前台应用,就会自动停止 如:nginx,启动后发现自己没有提供服务,就会立即停止,就没有程序了
查看日志
#自己编写一段脚本,并后台运行 [root@localhost /]# docker run -d centos /bin/sh -c "while true;do echo kuangshen;sleep 1;done" 85d460f6 [root@localhost /]# docker ps ConTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 85d460f6ad96 centos "/bin/sh -c 'while t…" 5 seconds ago Up -tf #显示日志 --tail number #要显示日志条数 [root@localhost /]# docker logs -tf --tail 10 85d460f6ad96
查看容器中的进程信息ps
docker top 容器id [root@localhost /]# docker top 85d460f6ad96 UID PID PPID C STIME TTY TIME CMD root 110110 110090 0 15:23 ? 00:00:00 /bin/sh -c while true;do echo kuangshen;sleep 1;done root 128910 110110 0 15:37 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1
查看镜像的元数据
docker inspect 容器id #返回有关 Docker 对象的详细信息
进入当前运行的容器
# 方式一 # 我们通常使用的容器都是后台方式运行的,进入容器,修改一些配置 docker exec -it 容器id bash or shell [root@localhost /]# docker exec -it 85d460f6ad96 /bin/bash [root@85d460f6ad96 /]# ls bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var [root@85d460f6ad96 /]# ps -ef 显示运行中的进程 UID PID PPID C STIME TTY TIME CMD root 1 0 0 07:23 ? 00:00:01 /bin/sh -c while true;do echo kuangshen;sleep 1;done root 1607 0 0 07:50 pts/0 00:00:00 /bin/bash
# 方式二 docker attach 容器id [root@localhost /]# docker attach 85d460f6ad96 正在执行的代码……
# 二者的区别 # docker exec #进入容器后开启一个新的线程,可以执行里面的 *** 作 # docker attach #进入容器正在执行的终端,不会启动新的进程
从容器内拷贝内容到主机上
[root@localhost home]# docker run -it centos /bin/bash [root@3fa32928910b /]# cd home [root@3fa32928910b home]# touch test.java 新建test.java文件 [root@3fa32928910b home]# ls test.java [root@3fa32928910b home]# exit exit 可以拷贝停止运行的容器 [root@localhost home]# docker cp 3fa32928910b:/home/test.java /home [root@localhost home]# ls admin test.java小结 作业 部署nginx
[root@localhost home]# docker search nginx 搜索镜像 [root@localhost home]# docker pull nginx 下载镜像 [root@localhost home]# docker run -d --name nginx01 -p 3344:80 nginx:9 启动镜像 # 后台启动 容器名 主机端口:容器端口 镜像:下载的nginx的版本号,默认是latest,如果存在的nginx不是最新的,会自动pull latest版本 -d 后台运行 --name 给容器起名 -p 宿主机端口:容器内部端口 87558db1c082123f6cbb50bc311f033253fc6722c0fbd678f42d9b7c925e0606 [root@localhost home]# docker ps 查看运行中的容器 ConTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 87558db1c082 nginx "/docker-entrypoint.…" 3 minutes ago Up 3 minutes 0.0.0.0:3344->80/tcp, :::3344->80/tcp nginx01 容器id 镜像名称 别名 [root@localhost home]# curl localhost:3344 本机测试3344端口 [root@localhost ~]# docker exec -it nginx01 /bin/bash 进入容器 root@87558db1c082:/# whereis nginx 查看nginx配置文件 nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx root@87558db1c082:/# cd /etc/nginx root@87558db1c082:/etc/nginx# ls conf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_params
端口暴露的概念
问题思考:我们每次改动nginx配置文件,都需要进入容器内部,十分麻烦,我要是可以在容器外部提供一个映射路径,达到修改容器名,容器内部就可以自动修改
部署tomcat[root@localhost ~]# docker pull tomcat 可以直接docker run 就会自动下载 [root@localhost ~]# docker run -d -p 3355:8080 --name tomcat01 tomcat d21f60cdaf09e1fcb8dc0a770492bf76c3f989ce9d4dc7c6e5b9d435faf328f0 [root@localhost ~]# docker exec -it tomcat01 /bin/bash root@d21f60cdaf09:/usr/local/tomcat# ls BUILDING.txt LICENSE README.md RUNNING.txt conf logs temp webapps.dist CONTRIBUTING.md NOTICE RELEASE-NOTES bin lib native-jni-lib webapps work #有webapps和webapps.dist两个文件,webapps里没有特权指令文件,webapps.dist才是我们要的指令文件 root@d21f60cdaf09:/usr/local/tomcat/webapps# ls root@d21f60cdaf09:/usr/local/tomcat/webapps# cd .. root@d21f60cdaf09:/usr/local/tomcat# cd webapps.dist/ root@d21f60cdaf09:/usr/local/tomcat/webapps.dist# ls ROOT docs examples host-manager manager root@d21f60cdaf09:/usr/local/tomcat/webapps.dist# cd .. root@d21f60cdaf09:/usr/local/tomcat# cp -r webapps.dist_data== 我们通过具名挂载可以方便找到我们的一个卷,大多数情况在使用具名挂载
-v 容器内路径 #匿名挂载 -v 自定义卷名:容器内路径 #具名挂载 -v /宿主机路径:容器内路径 #指定路径挂载拓展
# 通过 -v 容器内路径:ro rw 改变读写权限 ro(只读) rw(可读可写) # 一旦设置了容器权限,容器对我们挂载出来额内容就有限定了 [root@localhost home]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx [root@localhost home]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx # ro 只要看到ro就说明这个路径只能通过宿主机来 *** 作,容器内部是无法 *** 作的初始dockerfile
dockerfile 就是用来构建docker镜像的构建文件,命令脚本,使用docker build
通过这个脚本可以生成镜像,镜像是一层一层的,脚本是一个个的命令,每个命令都是一层
# 自己手写一个镜像 # 创建dockerfile,名字可以随机,建议dockerfile # 文件中的内容 指令(大写) 参数 [root@localhost docker-test-volume]# cat dockerfile #这里的每一个命令,就是镜像的一层 FROM centos VOLUME ["/volume01","/volume02"] CMD echo "----end------" CMD /bin/bash # 生成镜像,docker build -f 镜像文件 -t 镜像名:[tag] 当前目录(用 . 表示当前目录) [root@localhost docker-test-volume]# docker build -f dockerfile -t syw/centos:1.0 .
[root@localhost docker-test-volume]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE syw/centos 1.0 572699bf1784 3 minutes ago 209MB [root@localhost docker-test-volume]# docker run -it d230fdb6f988 [root@f0919d2736d4 /]# ls -l total 0 ... # 生成镜像时自动挂载的数据卷,这个卷和外部有一个同步的目录 drwxr-xr-x 2 root root 6 Jul 16 16:02 volume01 drwxr-xr-x 2 root root 6 Jul 16 16:02 volume02数据卷同步
这种方式以后用的很多,我们通常会构件自己的镜像,假设创建镜像时没有挂载卷,就要手动挂载卷 -v 卷名:容器内路径
在容器中,卷目录下创建的文件,会在外部有同步的文件
在卷中新建文件 [root@c2f68340ea32 /]# ls bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var volume01 volume02 [root@c2f68340ea32 /]# cd volume01 [root@c2f68340ea32 volume01]# touch test01.txt [root@c2f68340ea32 volume01]# ls test01.txt 查看容器的元数据信息 [root@localhost ~]# docker inspect c2f68340ea32 ..........找到mounts部分,查看容器内卷挂载的外部路径 "Mounts": [ { "Type": "volume", "Name": "b95f402df171463d2fb1d33730d76a29ea14a46c675f49bb5f1dd7c9ee1e5d48", "Source": "/var/lib/docker/volumes/b95f402df171463d2fb1d33730d76a29ea14a46c675f49bb5f1dd7c9ee1e5d48/_data", "Destination": "/volume01", "Driver": "local", "Mode": "", "RW": true, "Propagation": "" }, { "Type": "volume", "Name": "24b9d703c3ba734e82df6f2798f778c051530f07f9b09b4ad8fcc181d3fa8c55", "Source": "/var/lib/docker/volumes/24b9d703c3ba734e82df6f2798f778c051530f07f9b09b4ad8fcc181d3fa8c55/_data", "Destination": "/volume02", "Driver": "local", "Mode": "", "RW": true, "Propagation": "" } ] 查看外部同步的内容 [root@localhost ~]# cd /var/lib/docker/volumes/b95f402df171463d2fb1d33730d76a29ea14a46c675f49bb5f1dd7c9ee1e5d48/_data [root@localhost _data]# ls test01.txt数据卷容器
多个mysql同步数据
通过 syw/centos:1.0 镜像 创建并启动一个 叫docker01的容器 [root@localhost /]# docker run -it --name docker01 syw/centos:1.0 [root@9998f8ab8c5a /]# ls bin etc lib lost+found mnt proc run srv tmp var volume02 dev home lib64 media opt root sbin sys usr volume01 通过 syw/centos:1.0 镜像 创建并启动一个 叫docker02的容器 启动的时候 进行挂载,继承docker01 [root@localhost /]# docker run -it --name docker02 --volumes-from docker01 syw/centos:1.0 # 子容器 挂载 父容器 镜像 #进入docker01容器,创建文件,测试是否同步到docker02 [root@localhost /]# docker attach docker01 [root@9998f8ab8c5a /]# ls bin etc lib lost+found mnt proc run srv tmp var volume02 dev home lib64 media opt root sbin sys usr volume01 [root@9998f8ab8c5a /]# cd volume01 [root@9998f8ab8c5a volume01]# touch docker01 #退出docker01,进入docker02,发现容器间同步数据 [root@localhost /]# docker attach docker02 [root@7238a4895cdc /]# cd volume01 [root@7238a4895cdc volume01]# ls docker01
创建docker03容器,继承docker01
如果删除了docker01,继承docker01的依旧挂载了父容器
小结:
关键命令 --volumes-from 只要子容器挂载到父容器上就可以实现容器间的数据互相同步, 第三个容器的数据也可以同步到第一、第二个容器中,可以同步多个容器 就算删除docker01,docker02依然可以访问这个文件 这是容器间的拷贝的概念 容器之间的信息的传递,数据卷容器的生命周期一直持续到没有容器为止,但是一旦持续化到了本地,删除容器,本地的信息是不会被删除的dockerfile
dockerfile 就是用来构建docker镜像的构建文件,命令脚本参数
1、编写一个dockerfile文件 2、docker build 构建成为一个镜像 3、docker run 运行镜像 4、docker push 发布镜像
官方的做法
很多官方镜像都是基础包,很多功能没有(jdk+mysql+redis),我们通常会搭建自己的镜像,官方既然可以搭建镜像,我们自己也可以!
dockerfile搭建过程 基础知识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 #构建的时候设置环境变量实战测试
Docker Hub中99%的镜像都是从这个基础镜像 scratch 过来的,FROM scratch 然后配置需要的软件和配置来进行构建的
创建一个自己的dockerfile,增加官方centos没有的功能,如vim,net-tools
编写dockerfile文件
[root@localhost dockerfile]# vim mydockerfile-centos FROM centos #基于centos创建 MAINTAINER syw<2502708421@qq.com> ENV MYPATH /usr/local #运行时,进入容器的默认工作目录,pwd查看 WORKDIR $MYPATH # $表示取变量的值 RUN yum -y install vim RUN yum -y install net-tools #包名有问题,运行出错,认识过程 EXPOSE 80 CMD echo $MYPATH CMD echo "-----end-------" CMD /bin/bash # 设置默认的命令行
通过这个文件构建镜像
docker build -f dockerfile文件路径 -t(表示tag) 镜像名:[tag版本号] [root@localhost dockerfile]# docker build -f mydockerfile-centos -t mycentos:1.0 . 注意最后有个点
查看镜像的构建命令
docker history 创建的dockerfile镜像idCMD和ENTRYPOINT的区别
CMD #指定这个容器启动的时候需要运行的命令,只有最后一个会生效,可被替代 ENTRYPOINT #指定这个容器启动的时候需要运行的命令,可以追加命令
CMD中 替换 的含义
# 编写dockerfile文件 [root@localhost dockerfile]# vim CMDtest FROM centos CMD ["ls","-a"] #展示当前目录所有结构 # 构建镜像 [root@localhost dockerfile]# docker build -f CMDtest -t centoscmd . #镜像名一定为小写 # run ,发现 ls -a 命令生效了 [root@localhost dockerfile]# docker run b3f0497ff150 . .. .dockerenv bin dev etc home #正常运行 # 想追加一个命令的时候 -l ,实现 ls -al [root@localhost dockerfile]# docker run b3f0497ff150 -l "docker run" requires at least 1 argument. See 'docker run --help'. Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...] Run a command in a new container #出现报错,因为CMD把ls -a 替换成了 -l (CMD中的替换的含义)
ENTRYPOINT中 追加 的含义
# 编写dockerfile [root@localhost dockerfile]# vim ENTRYPOINTtest FROM centos ENTRYPOINT ["ls","-a"] # 构建镜像 [root@localhost dockerfile]# docker build -f CMDtest -t centoscmd . [root@localhost dockerfile]# docker run 43aa1c125f19 -l WARNING: IPv4 forwarding is disabled. Networking will not work. total 0 drwxr-xr-x 1 root root 6 Jul 17 07:35 . drwxr-xr-x 1 root root 6 Jul 17 07:35 .. -rwxr-xr-x 1 root root 0 Jul 17 07:35 .dockerenv # 追加一个命令 -l ,实际上执行的是 ls -al,并没有像cmd替换了-a命令
最好的学习就是对比
tomcat实战1、准备文件,把文件上传到本地
[root@localhost tomcat]# pwd /home/admin/build/tomcat [root@localhost tomcat]# ls apache-tomcat-9.0.50-deployer.tar.gz jdk-8u181-linux-x64.tar/2.gz
2、编写dockerfile文件,官方命名Dockerfile,build会自动寻找这个文件,就不需要-f指定了
FROM centos MAINTAINER admin<2502708421@qq.com> COPY readme.txt /usr/local/readme.txt 拷贝readme.txt 到容器内 /usr/local/readme.txt ADD jdk-8u181-linux-x64.tar.gz /usr/local #ADD 自动解压到/usr/local ADD apache-tomcat-9.0.50-deployer.tar.gz /usr/local RUN yum -y install vim #安装vim #配置环境变量 ENV MYPATH /usr/local #配置环境变量目录 WORKDIR $MYPATH #工作目录 ENV JAVA_HOME /usr/local/jdk1.8.0_181 #java的环境变量 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.50-deployer ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.50-deployer ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin EXPOSE 8080 # && 表示添加执行命令 CMD /usr/local/apache-tomcat-9.0.50-deployer/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.50-deployer/bin/logs/catalina.out
3、构造镜像
[root@localhost tomcat]# docker build -t diytomcat .
4、启动镜像
挂载了文件目录,挂载了日志目录 [root@localhost tomcat]# docker run -d -p 9090:8080 --name sywtomcat -v /home/admin/build/tomcat/test:/usr/local/apache-tomcat-9.0.50-deployer/webapps/test -v /home/admin/build/tomcat/tomcatlogs:/usr/local/apache-tomcat-9.0.50-deployer/logs diytomcat [root@localhost tomcat]# docker exec -it 3679e0964ee /bin/bash
在本地的/home/admin/build/tomcat/test目录下编写jsp文件,文件就可以自动同步到容器中,在宿主机浏览器测试,ip:映射端口号就可以访问tomcat服务器返回的jsp文件了。
5、发布项目(由于做了卷挂载,我们直接可以在本地编写项目,就可以发布了)
我们以后的开发步骤,需要掌握dockerfile的编写,我们以后的一切都是使用docker镜像来发布运行的
发布自己的镜像1、注册https://hub.docker.com/账号
2、在服务器上提交自己的镜像
[root@localhost ~]# 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 Username [root@localhost ~]# docker login -u 账号名 [root@localhost ~]# docker push syw/tomcat:5.0 The push refers to repository [docker.io/syw/tomcat] eb0d038a8c91: Preparing ed5c187d1a57: Preparing d9aae75ea5b5: Preparing 2653d992f4ef: Preparing denied: requested access to the resource is denied #虚拟机不允许发到docker hub上,因为要翻墙发布自己的镜像
1、注册https://hub.docker.com/账号
2、在服务器上提交自己的镜像
[root@localhost ~]# 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 Username [root@localhost ~]# docker login -u 账号名 [root@localhost ~]# docker push syw/tomcat:5.0 The push refers to repository [docker.io/syw/tomcat] eb0d038a8c91: Preparing ed5c187d1a57: Preparing d9aae75ea5b5: Preparing 2653d992f4ef: Preparing denied: requested access to the resource is denied #虚拟机不允许发到docker hub上,因为要翻墙发布到阿里云
找到容器镜像服务
创建镜像时,公有(别人可以访问),私有(只有自己访问),公网地址:可以通过该地址可以访问自己当前的仓库。
创建容器镜像
注意:密码需要在访问凭证那里设置,并用访问凭证密码在终端登录
补充:
docker load不能对载入的镜像重命名,而docker import可以为镜像指定新名称 docker load用来载入镜像包,docker import用来载入容器包,但两者都会恢复为镜像 docker save保存的是镜像,docker export保存的是容器docker网络 理解docker网络
清空所有环境 docker rmi -f $(docker images -aq) 获取当前ip地址 [root@localhost ~]# ip addr #docker0网卡 它作为桥梁,使得容器间可以互相通信
docker是如何处理容器访问网络的?下面生成一个容器进行测试
[root@localhost ~]# docker run -d -P --name tomcat01 tomcat #查看容器的内部网络容器地址 ip addr ,发现容器启动的时候会得到一个etho ip地址,docker发配的 [root@localhost ~]# docker exec -it tomcat01 ip addr 上面命令相当于 docker exec -it tomcat01 进入容器,但是没有打开交互命令行/bin/bash 直接执行 ip addr 1: lo: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 6: eth0@if7: 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通容器内部 [root@localhost ~]# 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.199 ms
原理
我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就有一个网卡docker0,桥接模式,使用的技术是evth-pair技术
启动了一个容器后再次测试 ip addr [root@localhost ~]# ip addr #与上面 6: eth0@if7 成对出现
发现又启动一个容器之前,多了一个262
与容器内的网卡6相似
再启动一个容器,再次 ip addr ,又多了一个网卡
容器内部 ip addr 发现和容器外部的网卡成对出现
# 我们发现这个容器带来的网卡都是一对对的 # evth-pair 就是一对虚拟设备接口,它们都是成对出现的,一段连着协议,一段彼此相连 # 正因为这个特性,evth-pair充当一个桥梁,连接各种虚拟网络设备 # OpenStack,docker容器间的连接,OVS的连接,都是使用evth-pair 技术
测试容器tomcat01、tomcat02 是否可以ping通
docker exec -it tomcat02 ping 172.18.0.2 说明容器和容器之间是可以通信的
原理图
结论:tomcat01和tomcat02是共用一个路由器,docker0
所有容器不指定网络的情况下,都是docker0路由的,docker会给我们的容器分配一个默认的可用ip
Docker使用的是linux的桥接,宿主机是一个docker容器的网桥
只要容器删除了,对应的网桥就没有了,ip addr 中对应的网卡也没了
思考一个场景,我们编写了一个微服务,database url=ip: ,项目不重启,数据库ip换掉,我们希望可以处理这个问题,可以名字来进行访问容器。不用网络地址可以ping通
[root@localhost ~]# docker exec -it tomcat01 ping tomcat02 ping: tomcat02: Name or service not known
如何解决这个问题?
# 添加了--link 实现容器名ping通,不需要通过网路ip [root@localhost ~]# docker run -d -P --name tomcat03 --link tomcat02 tomcat tomcat03 --link tomcay02 表示将tomcat03 link 到tomcat02 [root@localhost ~]# docker exec -it tomcat03 ping tomcat02 64 bytes from tomcat02 (172.17.0.3): icmp_seq=74 ttl=64 time=0.134 ms 64 bytes from tomcat02 (172.17.0.3): icmp_seq=75 ttl=64 time=0.156 ms # 反向不能ping通
docker inspect 容器id
其实这个tomcat03就是在本地配置了tomcat02的配置
[root@localhost ~]# docker exec -it tomcat03 cat /etc/hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.17.0.3 tomcat02 d8351e39a3c7 这里 172.17.0.4 e93babbd67a8
本质探究:–link就是我们在hosts配置中增加了一个 172.17.0.3 tomcat02 d8351e39a3c7 的配置
现在docker已经不建议用–link
主要用自定义网络,不适合docker0(不支持容器名连接访问)
查看所有的docker网络
[root@localhost ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 6b4e58745ca8 bridge bridge local 6e037e8fa416 host host local 437a79a1bd1a none null local
网络模式
bridge:桥接docker (默认,自己创建的网络也是用bridge 模式) none:不配置网络 host:和宿主机共享网络 container:容器网络连通(用的少,局限很大)
测试
# 我们直接启动命令,--net bridge,而这个就是我们的docker0 docker run -d -P --name tomcat01 tomcat docker run -d -P --name tomcat01 --net bridge tomcat #等同于上一个命令 # docker0特点,默认,域名不能访问,--link 可以打通! # 自定义网络 [root@localhost ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet --driver : 创建一个网络 bridge:桥接的默认模式 --subnet : 创建子网 16 表示可以创建65536个子网 从192.168.0.0 到 192.168.255.255 --gateway : 默认路由 mynet : 网络名称 e9f5bbedbd719f2a83e86151898e63ee0b046ffc4d13de64f64791f1781904d4 #注意:不可以与自己的终端连接同一网段和网关,否则产生冲突 [root@localhost ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 6b4e58745ca8 bridge bridge local 6e037e8fa416 host host local e9f5bbedbd71 mynet bridge local 437a79a1bd1a none null local
自己的网络就创建好了,后期就可以把自己的服务放到自己的网络里
查看元数据
启动两个容器
[root@localhost ~]# docker run -d -P --name tomcat-net-01 --net mynet tomcat 968477f8b2330669ca9dfed713f1ad277d413dc8216246dcfc8b72c118322e7f [root@localhost ~]# docker run -d -P --name tomcat-net-02 --net mynet tomcat 2ff8d58d4d34c2e52a41247b115e6a6ef4d3dffa69f61e7afabdee960e1f55ef [root@localhost ~]# docker network inspect mynet [ { "Name": "mynet", "Id": "e9f5bbedbd719f2a83e86151898e63ee0b046ffc4d13de64f64791f1781904d4", "Created": "2021-07-18T16:31:54.338626301+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": { "2ff8d58d4d34c2e52a41247b115e6a6ef4d3dffa69f61e7afabdee960e1f55ef": { "Name": "tomcat-net-02", "EndpointID": "81f1f522143adfb96e2e521ec8b43fbc5c1cd52acd9061433e6003a5e527ecd0", "MacAddress": "02:42:c0:a8:00:03", "IPv4Address": "192.168.0.3/16", "IPv6Address": "" }, "968477f8b2330669ca9dfed713f1ad277d413dc8216246dcfc8b72c118322e7f": { "Name": "tomcat-net-01", "EndpointID": "07e62fb9172718b3ba337074ca1b6bdf757fb33c0103159f9f1a711f4927611c", "MacAddress": "02:42:c0:a8:00:02", "IPv4Address": "192.168.0.2/16", "IPv6Address": "" } }, "Options": {}, "Labels": {} } ]
发现不使用–link都可以ping通
[root@localhost ~]# docker exec -it tomcat-net-01 ping 192.168.0.3 [root@localhost ~]# docker exec -it tomcat-net-01 ping tomcat-net-02
我们自定义的网络docker都已经帮我们维护好了对应的关系,推荐我们平时这样使用网络
好处:
Redis 不同的集群使用不同的网络,保证集群是安全和健康的
mysql 不同的集群使用不同的网络,保证集群是安全和健康的
通过打通容器和网卡mynet
实现连通不同网卡下的容器
测试打通 tomcat01(属于172.17.0.0/16) -mynet
生成tomcat01容器 [root@localhost ~]# docker run -d -P --name tomcat01 tomcat c3054639c41f17
测试两个不同网段的容器连接
[root@localhost ~]# docker network connect mynet tomcat01 [root@localhost ~]# docker network inspect mynet 查看,发现将tomcat01容器连通到了mynet网卡,容器和网络打通了 # 一个容器两个ip地址,类似阿里云服务器:公网ip 私网ip
实现了跨网段用名称进行通信
[root@localhost ~]# docker exec -it tomcat01 ping tomcat-net-01 tomcat02 和mynet是依旧没有连通的 [root@localhost ~]# docker exec -it tomcat02 ping tomcat-net-01
结论:假设要跨网段 *** 作别人,就需要使用docker network connect 连通
实战:部署Redis集群
测试六台服务器的集群,r-m3宕机,r-s3替补
# 创建redis网卡 [root@localhost ~]# docker network create redis --subnet 172.38.0.0/16 95d43efc681975cab5da8d8c6344438ee0654dd2f31592afe7552be930c385ab # 通过脚本创建六个redis配置 for port in $(seq 1 6); do mkdir -p /mydata/redis/node-${port}/conf touch /mydata/redis/node-${port}/conf/redis.conf cat << EOF >/mydata/redis/node-${port}/conf/redis.conf port 6379 bind 0.0.0.0 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 cluster-announce-ip 172.38.0.1${port} cluster-announce-port 6379 cluster-announce-bus-port 16379 appendonly yes EOF done [root@localhost ~]# cd /mydata [root@localhost mydata]# ls redis [root@localhost mydata]# cd redis/ [root@localhost redis]# ls node-1 node-2 node-3 node-4 node-5 node-6 # 启动六个redis docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port} -v /mydata/redis/node-${port}/data:/data -v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.38.0.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf; # 启动第一个 docker run -p 6371:6379 -p 16371:16379 --name redis-1 -v /mydata/redis/node-1/data:/data -v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf #进入其一个redis [root@localhost redis]# docker exec -it redis-1 /bin/sh /data #
创建集群的配置
/data # redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1 >>> Performing hash slots allocation on 6 nodes... Master[0] -> Slots 0 - 5460 Master[1] -> Slots 5461 - 10922 Master[2] -> Slots 10923 - 16383 Adding replica 172.38.0.15:6379 to 172.38.0.11:6379 Adding replica 172.38.0.16:6379 to 172.38.0.12:6379 Adding replica 172.38.0.14:6379 to 172.38.0.13:6379 M: 60438cf4aecf3b0e8a61f69f36084608eabea0ef 172.38.0.11:6379 slots:[0-5460] (5461 slots) master M: 4cd57656a08a2c49a132b8187480f74c99c1759b 172.38.0.12:6379 slots:[5461-10922] (5462 slots) master M: 1686c456274f1429eb74222b1eb5e55e641bb983 172.38.0.13:6379 slots:[10923-16383] (5461 slots) master S: cd8444d88e3a9cb494ce84edfdc163757f3b61dd 172.38.0.14:6379 replicates 1686c456274f1429eb74222b1eb5e55e641bb983 S: e706e3562994488db2dc94cb5aa0d02ee2f64f9d 172.38.0.15:6379 replicates 60438cf4aecf3b0e8a61f69f36084608eabea0ef S: e543c17775f8e48cd9019bd3535dc3e8a5a54ff1 172.38.0.16:6379 replicates 4cd57656a08a2c49a132b8187480f74c99c1759b Can I set the above configuration? (type 'yes' to accept): yes #问是否要配置是哪 个主机,三个从机,回答yes >>> Nodes configuration updated >>> Assign a different config epoch to each node >>> Sending CLUSTER MEET messages to join the cluster Waiting for the cluster to join .. >>> Performing Cluster Check (using node 172.38.0.11:6379) M: 60438cf4aecf3b0e8a61f69f36084608eabea0ef 172.38.0.11:6379 slots:[0-5460] (5461 slots) master 1 additional replica(s) S: e706e3562994488db2dc94cb5aa0d02ee2f64f9d 172.38.0.15:6379 slots: (0 slots) slave replicates 60438cf4aecf3b0e8a61f69f36084608eabea0ef M: 1686c456274f1429eb74222b1eb5e55e641bb983 172.38.0.13:6379 slots:[10923-16383] (5461 slots) master 1 additional replica(s) M: 4cd57656a08a2c49a132b8187480f74c99c1759b 172.38.0.12:6379 slots:[5461-10922] (5462 slots) master 1 additional replica(s) S: cd8444d88e3a9cb494ce84edfdc163757f3b61dd 172.38.0.14:6379 slots: (0 slots) slave replicates 1686c456274f1429eb74222b1eb5e55e641bb983 S: e543c17775f8e48cd9019bd3535dc3e8a5a54ff1 172.38.0.16:6379 slots: (0 slots) slave replicates 4cd57656a08a2c49a132b8187480f74c99c1759b [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.
/data # redis-cli -c #redis-cli 连接的是单机,-c 可以连接到集群 127.0.0.1:6379> cluster nodes
测试
127.0.0.1:6379> set a b -> Redirected to slot [15495] located at 172.38.0.13:6379 OK #将redis-3服务停止,在redis-4中get到 172.38.0.13:6379> get a -> Redirected to slot [15495] located at 172.38.0.14:6379 "b"Springboot微服务打包Docker镜像
构建项目,打包
打包后进入目录,命令行测试jar包是否可以运行
编写dockerfile文件
发布docker
将发布的内容上传到服务器
build构建镜像
运行镜像,curl测试
忘记一个命令是什么,可以docker ex 然后按tab键,会提示相关的命令
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)