1 Docker简介
1.1 什么是虚拟化
在计算机中,虚拟化(英语:Virtualization)是一种资源管理技术,是将计算机的各种实体资源,如服务器、网络、内存及存储等,予以抽象、转换后呈现出来,打破实体结构间的不可切割的障碍,使用户可以比原本的组态更好的方式来应用这些资源。这些资源的新虚拟部份是不受现有资源的架设方式,地域或物理组态所限制。一般所指的虚拟化资源包括计算能力和资料存储。
在实际的生产环境中,虚拟化技术主要用来解决高性能的物理硬件产能过剩和老的旧的硬件产能过低的重组重用,透明化底层物理硬件,从而最大化的利用物理硬件 对资源充分利用
虚拟化技术种类很多,例如:软件虚拟化、硬件虚拟化、内存虚拟化、网络虚拟化(vip)、桌面虚拟化、服务虚拟化、虚拟机等等。
1.2 什么是Docker
Docker 是一个开源项目,诞生于 2013 年初,最初是 dotCloud 公司内部的一个业余项目。它基于 Google 公司推出的 Go 语言实现。 项目后来加入了 Linux 基金会,遵从了 Apache 2.0 协议,项目代码在 GitHub 上进行维护。
Docker 自开源后受到广泛的关注和讨论,以至于 dotCloud 公司后来都改名为 Docker Inc。Redhat 已经在其 RHEL6.5 中集中支持 Docker;Google 也在其 PaaS 产品中广泛应用。
Docker 项目的目标是实现轻量级的操作系统虚拟化解决方案。 Docker 的基础是 Linux 容器(LXC)等技术。
在 LXC 的基础上 Docker 进行了进一步的封装,让用户不需要去关心容器的管理,使得操作更为简便。用户操作 Docker 的容器就像操作一个快速轻量级的虚拟机一样简单。
为什么选择Docker?
(1)上手快。
用户只需要几分钟,就可以把自己的程序“Docker化”。Docker依赖于“写时复制”(copy-on-write)模型,使修改应用程序也非常迅速,可以说达到“随心所致,代码即改”的境界。
随后,就可以创建容器来运行应用程序了。大多数Docker容器只需要不到1秒中即可启动。由于去除了管理程序的开销,Docker容器拥有很高的性能,同时同一台宿主机中也可以运行更多的容器,使用户尽可能的充分利用系统资源。
(2)职责的逻辑分类
使用Docker,开发人员只需要关心容器中运行的应用程序,而运维人员只需要关心如何管理容器。Docker设计的目的就是要加强开发人员写代码的开发环境与应用程序要部署的生产环境一致性。从而降低那种“开发时一切正常,肯定是运维的问题(测试环境都是正常的,上线后出了问题就归结为肯定是运维的问题)”
(3)快速高效的开发生命周期
Docker的目标之一就是缩短代码从开发、测试到部署、上线运行的周期,让你的应用程序具备可移植性,易于构建,并易于协作。(通俗一点说,Docker就像一个盒子,里面可以装很多物件,如果需要这些物件的可以直接将该大盒子拿走,而不需要从该盒子中一件件的取。)
(4)鼓励使用面向服务的架构
Docker还鼓励面向服务的体系结构和微服务架构。Docker推荐单个容器只运行一个应用程序或进程,这样就形成了一个分布式的应用程序模型,在这种模型下,应用程序或者服务都可以表示为一系列内部互联的容器,从而使分布式部署应用程序,扩展或调试应用程序都变得非常简单,同时也提高了程序的内省性。(当然,可以在一个容器中运行多个应用程序)
1.3 容器与虚拟机比较
下面的图片比较了 Docker 和传统虚拟化方式的不同之处,可见容器是在操作系统层面上实现虚拟化,直接复用本地主机的操作系统,而传统方式则是在硬件层面实现。
与传统的虚拟机相比,Docker优势体现为启动速度快、占用体积小。
1.4 Docker 组件
1.4.1 Docker服务器与客户端
Docker是一个客户端-服务器(C/S)架构程序。Docker客户端只需要向Docker服务器或者守护进程发出请求,服务器或者守护进程将完成所有工作并返回结果。Docker提供了一个命令行工具Docker以及一整套RESTful API。你可以在同一台宿主机上运行Docker守护进程和客户端,也可以从本地的Docker客户端连接到运行在另一台宿主机上的远程Docker守护进程。
1.4.2 Docker镜像与容器
镜像是构建Docker的基石。用户基于镜像来运行自己的容器。镜像也是Docker生命周期中的“构建”部分。镜像是基于联合文件系统的一种层式结构,由一系列指令一步一步构建出来。例如:
添加一个文件;
执行一个命令;
打开一个窗口。
也可以将镜像当作容器的“源代码”。镜像体积很小,非常“便携”,易于分享、存储和更新。
Docker可以帮助你构建和部署容器,你只需要把自己的应用程序或者服务打包放进容器即可。容器是基于镜像启动起来的,容器中可以运行一个或多个进程。我们可以认为,镜像是Docker生命周期中的构建或者打包阶段,而容器则是启动或者执行阶段。 容器基于镜像启动,一旦容器启动完成后,我们就可以登录到容器中安装自己需要的软件或者服务。
所以Docker容器就是:
一个镜像格式;
一些列标准操作;
一个执行环境。
Docker借鉴了标准集装箱的概念。标准集装箱将货物运往世界各地,Docker将这个模型运用到自己的设计中,唯一不同的是:集装箱运输货物,而Docker运输软件。
和集装箱一样,Docker在执行上述操作时,并不关心容器中到底装了什么,它不管是web服务器,还是数据库,或者是应用程序服务器什么的。所有的容器都按照相同的方式将内容“装载”进去。
Docker也不关心你要把容器运到何方:我们可以在自己的笔记本中构建容器,上传到Registry,然后下载到一个物理的或者虚拟的服务器来测试,在把容器部署到具体的主机中。像标准集装箱一样,Docker容器方便替换,可以叠加,易于分发,并且尽量通用。
1.4.3 Registry(注册中心)
Docker用Registry来保存用户构建的镜像。Registry分为公共和私有两种。Docker公司运营公共的Registry叫做Docker Hub。用户可以在Docker Hub注册账号,分享并保存自己的镜像(说明:在Docker Hub下载镜像巨慢,可以自己构建私有的Registry)。
Docker安装与启动
2.1 安装Docker
Docker官方建议在Ubuntu中安装,因为Docker是基于Ubuntu发布的,而且一般Docker出现的问题Ubuntu是最先更新或者打补丁的。在很多版本的CentOS中是不支持更新最新的一些补丁包的。
由于我们学习的环境都使用的是CentOS,因此这里我们将Docker安装到CentOS上。注意:这里建议安装在CentOS7.x以上的版本,在CentOS6.x的版本中,安装前需要安装其他很多的环境而且Docker很多补丁不支持更新。
请直接挂载课程配套的Centos7.x镜像
(1)yum 包更新到最新
sudo yum update
(2)安装需要的软件包, yum-util 提供yum-config-manager功能,另外两个是devicemapper驱动依赖的
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
(3)设置yum源为阿里云
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
(4)安装docker
sudo yum install docker-ce
(5)安装后查看docker版本
docker -v
2.2 设置ustc的镜像
ustc是老牌的linux镜像服务提供者了,还在遥远的ubuntu 5.04版本的时候就在用。ustc的docker镜像加速器速度很快。ustc docker mirror的优势之一就是不需要注册,是真正的公共服务。
https://lug.ustc.edu.cn/wiki/mirrors/help/docker
编辑该文件:
vi /etc/docker/daemon.json
在该文件中输入如下内容:
{
"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"]
}
2.3 Docker的启动与停止
systemctl命令是系统服务管理器指令
启动docker:
systemctl start docker
停止docker:
systemctl stop docker
重启docker:
systemctl restart docker
查看docker状态:
systemctl status docker
开机启动:
systemctl enable docker
查看docker概要信息
docker info
查看docker帮助文档
docker --help
3 常用命令
3.1 镜像相关命令
3.1.1 查看镜像
docker images
REPOSITORY:镜像名称
TAG:镜像标签
IMAGE ID:镜像ID
CREATED:镜像的创建日期(不是获取该镜像的日期)
SIZE:镜像大小
这些镜像都是存储在Docker宿主机的/var/lib/docker目录下
3.1.2 搜索镜像
如果你需要从网络中查找需要的镜像,可以通过以下命令搜索
docker search 镜像名称
NAME:仓库名称
DESCRIPTION:镜像描述
STARS:用户评价,反应一个镜像的受欢迎程度
OFFICIAL:是否官方
AUTOMATED:自动构建,表示该镜像由Docker Hub自动构建流程创建的
3.1.3 拉取镜像
拉取镜像就是从中央仓库中下载镜像到本地
docker pull 镜像名称
例如,我要下载centos7镜像
docker pull centos:7
3.1.4 删除镜像
按镜像ID删除镜像
docker rmi 镜像ID
删除所有镜像
docker rmi `docker images -q`
3.2 容器相关命令
3.2.1 查看容器
查看正在运行的容器
docker ps
查看所有容器
docker ps –a
查看最后一次运行的容器
docker ps –l
查看停止的容器
docker ps -f status=exited
3.2.2 创建与启动容器
创建容器常用的参数说明:
创建容器命令:docker run
-i:表示运行容器
-t:表示容器启动后会进入其命令行。加入这两个参数后,容器创建就能登录进去。即分配一个伪终端。
--name :为创建的容器命名。
-v:数据挂载会常用到。表示目录映射关系(前者是宿主机目录,后者是映射到宿主机上的目录),可以使用多个-v做多个目录或文件映射。注意:最好做目录映射,在宿主机上做修改,然后共享到容器上。
-d:在run后面加上-d参数,则会创建一个守护式容器在后台运行(这样创建容器后不会自动登录容器,如果只加-i -t两个参数,创建后就会自动进去容器)。
-p:表示端口映射,前者是宿主机端口,后者是容器内的映射端口。可以使用多个-p做多个端口映射
(1)交互式方式创建容器
docker run -it --name=容器名称 镜像名称:标签 /bin/bash
这时我们通过ps命令查看,发现可以看到启动的容器,状态为启动状态
退出当前容器
exit
(2)守护式方式创建容器:
docker run -di --name=容器名称 镜像名称:标签
登录守护式容器方式:
docker exec -it 容器名称 (或者容器ID) /bin/bash
删除容器:
docker rm -f [容器名字]
3.2.3 停止与启动容器
停止容器:
docker stop 容器名称(或者容器ID)
启动容器:
docker start 容器名称(或者容器ID)
3.2.4 文件拷贝
如果我们需要将文件拷贝到容器内可以使用cp命令
docker cp 需要拷贝的文件或目录 容器名称:容器目录
也可以将文件从容器内拷贝出来
docker cp 容器名称:容器目录 需要拷贝的文件或目录
3.2.5 目录挂载
我们可以在创建容器的时候,将宿主机的目录与容器内的目录进行映射,这样我们就可以通过修改宿主机某个目录的文件从而去影响容器。 创建容器 添加-v参数 后边为 宿主机目录:容器目录,例如:
docker run -di -v /usr/local/myhtml:/usr/local/myhtml --name=mycentos3 centos:7
如果你共享的是多级的目录,可能会出现权限不足的提示。
这是因为CentOS7中的安全模块selinux把权限禁掉了,我们需要添加参数 --privileged=true 来解决挂载的目录没有权限的问题
3.2.6 查看容器IP地址
我们可以通过以下命令查看容器运行的各种数据
docker inspect 容器名称(容器ID)
也可以直接执行下面的命令直接输出IP地址
docker inspect --format=\'{{.NetworkSettings.IPAddress}}\' 容器名称(容器ID)
3.2.7 删除容器
删除指定的容器:
docker rm 容器名称(容器ID)
4 应用部署
4.1 MySQL部署
(1)拉取mysql镜像
docker pull centos/mysql-57-centos7
(2)创建容器
docker run -di --name=tensquare_mysql -p 33306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql
-p 代表端口映射,格式为 宿主机映射端口:容器运行端口
-e 代表添加环境变量 MYSQL_ROOT_PASSWORD 是root用户的登陆密码
(3)远程登录mysql
连接宿主机的IP ,指定端口为33306
4.2 tomcat部署
(1)拉取镜像
docker pull tomcat:7-jre7
(2)创建容器
创建容器 -p表示地址映射
docker run -di --name=mytomcat -p 9000:8080
-v /usr/local/webapps:/usr/local/tomcat/webapps tomcat:7-jre7
4.3 Nginx部署
(1)拉取镜像
docker pull nginx
(2)创建Nginx容器
docker run -di --name=mynginx -p 80:80 nginx
4.4 Redis部署
(1)拉取镜像
docker pull redis
(2)创建容器
docker run -di --name=myredis -p 6379:6379 redis
commit 镜像
命令和git 原理类似
语法:
docker commit -a="作者" -m="提交的描述信息" 容器id 目标镜像名:【TAG】
解释:docker commit -a="abiu" -m="测试提交一个自己的镜像" 123456(这个意思是容器id) tomcat01:1.0(意思是起的镜像名字冒号:版本号1.0)
5 迁移与备份
5.1 容器保存为镜像
我们可以通过以下命令将容器保存为镜像
docker commit mynginx mynginx_i
5.2 镜像备份
我们可以通过以下命令将镜像保存为tar 文件
docker save -o mynginx.tar mynginx_i
5.3 镜像恢复与迁移
首先我们先删除掉mynginx_img镜像 然后执行此命令进行恢复
docker load -i mynginx.tar
-i 输入的文件
执行后再次查看镜像,可以看到镜像已经恢复
容器数据卷
docker 理念:就是将应用和环境打包成一个镜像!
出现的问题:如果数据都在容器中,那么我们把容器删除,数据就会丢失。
怎么可以数据持久化???mysql 数据怎么存储在本地?
容器之间可以有一个数据共享技术!docker 容器中产生的数据,同步到本地。这就是卷技术,就是目录的挂载。将容器的目录,挂在到Linux上面。
使用数据卷:
方式一:直接使用命令来挂载 -v
语法: docker run -it -v -p 主机目录:容器目录
实例: docker run -it -v /home/ceshi:/home centos /bin/bash
/home/ceshi 是虚拟机的home 文件下,新建了一个ceshi 目录,里面放的
是docker 的home 目录下 centos镜像里/bin/bash 目录下的数据文件
这样就把容器里的数据给挂载出去了,并且是双向绑定,主机的数据改变,会相应到容器里的数据。
实战:安装一个MySql,数据持久化问题。
下载mysql5.7版本 镜像: docker pull mysql:5.7
创建并启动容器,并且挂载(v)到主机上的home 目录下,并且配置(e 就代表要配置):挂载多个目录
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
具名和匿名挂载
# 匿名挂载
-v 容器内路径
实例: docker run -d -P --name nginx01 -v /ect/nginx nginx
然后可以查看本地的镜像: docker volume ls
这时候发现一大堆字符,但是没有具体的名字,因为没有指定挂载的名字,所以是匿名的。
# 具名挂载(常用)
命令实例: docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
然后执行 docker volume ls 查看可以发现,和匿名挂载不一样的是,最下面有一个名字为:juming-nginx 的名字
这样可以命令查看挂载的位置在哪里: docker volume inspect juming-nginx
执行后发现,出来的几个属性,Mountpoint 属性的值的目录,就是这个具名挂载的目录。
其实可以得出结论:没有指定目录的情况下,都是挂载到了 /var/lib/docker/volumes/xxxxxxx 的目录下
【扩展:ro/rw】
常见的比如:
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx
这个就是挂载时候设置了权限,ro 就是只读,rw 就是可读可写(默认的就是rw),如果设置了ro 权限,就不可以更改了,只能从主机(虚拟机)上面更改,容器内部是无法操作的啦!
6 Dockerfile
6.1 什么是Dockerfile
Dockerfile是由一系列命令和参数构成的脚本,这些命令应用于基础镜像并最终创建一个新的镜像。
1、对于开发人员:可以为开发团队提供一个完全一致的开发环境; 2、对于测试人员:可以直接拿开发时所构建的镜像或者通过Dockerfile文件构建一个新的镜像开始工作了; 3、对于运维人员:在部署时,可以实现应用的无缝移植。
构建步骤:
1、编写一个dockerfile文件
2、docker build 构建成为一个镜像
3、docker run 运行镜像
4、docker push 发布镜像
6.2 常用命令
| 命令 | 作用 |
|---|---|
| FROM image_name:tag | 定义了使用哪个基础镜像启动构建流程 |
| MAINTAINER user_name | 声明镜像的创建者 |
| ENV key value | 设置环境变量 (可以写多条) |
| RUN command | 是Dockerfile的核心部分(可以写多条) |
| ADD source_dir/file dest_dir/file | 将宿主机的文件复制到容器内,如果是一个压缩文件,将会在复制后自动解压 |
| COPY source_dir/file dest_dir/file | 和ADD相似,但是如果有压缩文件并不能解压 |
| WORKDIR path_dir | 设置工作目录 |
方式二挂载
镜像是一层一层的,所以命令也就是一个一个的命令,一个命令就是镜像的一层
实例:创建一个dockerfile文件,名字可以随便写,建议用dockerfile 为名字
创建的dockerfile文件,里面写的指令和参数:(指令必须是大写的)
FROM centos VOLUME ["volume01","volume02"] CMD echo "--end--" CMD /bin/bash
然后可以再用 docker run -it xxx... 来启动自己定义的容器,然后ls 查看可以发现,会有volume01,volume02 挂载的,既然是挂载的,那么肯定有一个同步目录在宿主机上。
容器数据卷
就是容器之间互相挂载,比如docker run -it 。。。启动挂载一个容器docker01,
然后再启动挂载一个docker02,这个docker02挂载的是docker01的目录。
实例:docker run -it --name docker02 --volumes-from docker01 容器名:版本号 (不想用容器名+版本号就用容器id也可以)
这个--volumes-from 意思就等于是docke2继承了docker01
如果把宿主机(docker01挂载的目录)的数据改变,docker01和docker02的数据都会改变,会同步到docker02的。
也可以在创建docker03来继承docker01也是可以的,
它们之间是数据共享并且属于数据备份的,如果把docker01直接删除,docker02 和03 还是有docker01的
6.3 使用脚本创建镜像
# FROM 基础镜像,一切从这开始构建,比如写centos,代表的是一个电脑,虚拟机,系统,这个意思 # MAINTINER 镜像谁写的,作者信息,姓名+邮箱 # RUN 镜像构建时候需要运行,一个命令代表而已 # ADD 步骤,添加内容,比如添加一个tomcat镜像到这个centos里了的意思 # WORKDIR 镜像工作目录,指定目录的 # VOLUME 挂载的目录 # EXPOSE 对外暴漏端口的作用,和-p 指令一样 # CMD 指定容器启动时候要运行的命令,只有最后一个生效,可以被替代 # ENTRYPOINT 和这个CMD 作用一样,但,不同的是,可以追加命令,区别就是,一个是替换,一个是追加 # ONBUILD 当构建一个被继承DockerFile 时候就会运行这个 ONBUILD 指令,这个是触发指令 # COPY 类似ADD 命令,把文件拷贝到镜像中 # ENV 构建时候设置环境变量
示例1:
创建目录: mkdir dockerfile
进入这个目录: cd dockerfile
新建一个文本写脚本: vim mydockerfile-centos
写的脚本内容:
FROM centos MAINTAINER wangbiao<1371850216@qq.com> ENV MYPATH /usr/local 设置环境变量,指定工作目录,这个就和配置java的JAVA_HOME一样 WORKDIR $MYPATH 指定路径,用$ 符号 RUN yum -y install vim 执行命令,安装一个vim 命令 RUN yum -y install net-tools 这个是执行安装一个ifconfig 命令,这两个命令在docker的基本镜像里是没有的 EXPOSE 80 暴露80 端口
CMD echo $MYPATH 输出MYPATH路径,看能否输出
CMD echo "-------end-------" 输出一个end,可以说明执行完了
CMD /bin/bash 进入到/bin/bash 命令行
然后保存退出,当然也可以查一下自己写的:cat mydockerfile-centos
接下来可以build 构建文件了,
命令:docker build -f mydockerfile-centos -t mycentos:0.1 .
*命令说明: build:构建 -f: 构建谁?这个mydockerfile-centos -t:创建镜像,后面写名字及版本号,最后还有一个点 .
执行就可以了,成功会在下面显示: Successfully built xxxxxxxx 和Successfully tagged mycentos:0.1 (这个是刚刚自己起的镜像名)
成功就可以测试运行:
查看一下镜像: docker images 会发现自己刚刚构建的镜像
然后运行: docker run -it mycentos:0.1 就可以进入这个镜像
pwd 查看可以之间看到了 /usr/local 这个刚刚自己设置的目录,默认的那个centos 的工作目录是根目录
然后做重要的是要试一试ifconfig 和vim 这两个命令,发现可以用了,OK说明自己构建的镜像成功啦!!
并且也可以看看某个镜像是怎么做出来的,命令:
docker history 镜像id 就可以查看步骤了
演示CMD 和ENTRYPOINT 区别:
CMD:
首先随便创建一个文件:vim dockerfile-cmd-test
编写dockerfile 命令:
FROM centos
CMD ["ls","-a"] 好啦,就这么简单,这个命令就是显示所有目录结构,然后退出并保存
然后构建:
docker build -f dockerfile-cmd-test -t cmdtest .
然后执行:
docker run 镜像id(构建的dockerfile-cmd-test的镜像id)
发现 ls -a生效了
但是,如果执行命令 ls -al 替换ls -a 会发现是可以替换掉的
docker run 镜像id ls -al
ENTRYPOINT
跟刚才测试的CMD一样,把名字换一下就行了,命令脚本写:
FROM centos
ENTRYPOINT ["ls","-a]
然后一样的build 构建一下,构建以后再执行:
docker run 镜像id -l
发现是可以直接运行成功的,这样就说明是直接追加的,ls -a 就变成了 ls -al 啦!它是不会替换原来的命令的
实战一个Tomcat 镜像:
1、准备镜像文件tomcat压缩包、jdk的压缩包 因为tomcat是在java环境下的
2、编写dockerfile 文件
vim Dokcerfile 新建并编写一个dockerfile文件,这个Dockerfile 名字是固定写法,build 时候就会自动去寻找
touch readme.txt 新建一个文本
Dockerfile文件里写命令:
FROM centos MAINTAINER wangbiao<1371850216@qq.com> COPY readme.txt /usr/local/readme.txt 拷贝这个文本 ADD jdk的压缩包 /usr/local 这个ADD 命令添加jdk压缩包时候,会自动解压的! ADD tomcat压缩包名 /usr/local 这两个压缩包都添加并解压到 /usr/local目录下了 RUN yum -y install vim 添加vim 命令 ENV MYPATH /usr/local 配置环境变量 WORKDIR $MYPATH 指定工作目录 ENV JAVA_HOME /usr/local/jdk1.8 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/tomcat-9.0 ENV CATALINA_BASH /usr/local/tomcat-9.0 # 这几步是配置jdk和tomcat的环境变量 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin # 配置总的 EXPOSE 8080 # 暴露tomcat端口 CMD /usr/local/tomcat-9.0/bin/startup.sh && tail -F /usr/local/tomcat-9.0/bin/logs/catalina.out # 直接启动tomcat,并显示日志信息
然后就可以build 这个Dockerfile,因为这个名字是规范写法,所以直接build 就可以自己去找这个文件
docker build -t diytomcat .
之前取的名字不是Dockerfile这个标准,所以才要-f 去寻找
构建好以后,docker images 查看镜像是否OK
OK以后就可以启动这个镜像了:
docker run -d -p 9090:8080 --name diytomcat -v /home/wangbiao/build/tomcat/test:/usr/local/tomcat-9.0/webapps/test -v /home/wangbiao/build/tomcat/tomcatlogs/:/usr/local/tomcat-9.0/logs diytomcat
这个启动镜像命令有点长,-d 后台运行,-v 挂载tomcat-9.0的webapps到宿主机上,tomcat-9.0的日志也挂载宿主机上,挂载的镜像是diytomcat 这个刚刚自定义的dockerfile文件的镜像
然后就可以进入目录:docker exec -it 启动这个镜像的id 目录
来查看
这样,我们直接在本地写项目,上传到宿主机就可以自动发布到镜像上了,比如:在宿主机上添加编写目录,WEB-INF,在里面建个web.xml 文件,随便找个web.xml 粘过来,保存退出,
然后在返回WEB-INF统计目录上,也就是这个web.xml上级目录,随便建个index.html 或者jsp,或者粘过来一个。
大功告成,访问浏览器,ip端口号路径名(就是index.html在哪个目录下)
发布自己的镜像:
发布到DockerHub上
首先要注册自己的dockerhub账号,确定这个账号可以登录,然后在服务器上提交
总之很简单:
docker login -u 注册的名字
回车执行以后会让输入密码
登陆成功然后就可以提交了
docker pull wangbiao/diytomcat:1.0 最好是带上自己名字和版本号,因为可能有很多人都提交一样的名字的镜像,当然不带自己名字也可以,但是可能会被拒绝。。
如果实在提交不成功,版本号什么重复的话,可以给镜像加个版本号:
语法:
docker tag 镜像id 新名字:版本号
查看镜像,重新提交
发布到阿里云
登录阿里云,找到容器服务,创建命名空间,再创建容器镜像(在左边镜像仓库里)
1个账号只能创建3个命名空间
创建玩以后,点击镜像直接进去浏览,会有详细教程步骤。
一样的登录:docker login --username=xxxxx 的那一行复制过来直接执行
然后 docker pull 镜像名:版本号 直接执行就发布了。
发布以后点击左边 镜像版本 就可以看到会有一个版本,别人就可以下载
示例2:
(1)创建目录
mkdir –p /usr/local/dockerjdk8
(2)下载jdk-8u171-linux-x64.tar.gz并上传到服务器(虚拟机)中的/usr/local/dockerjdk8目录
(3)创建文件Dockerfile vi Dockerfile
#依赖镜像名称和ID
FROM centos:7
#指定镜像创建者信息
MAINTAINER ITCAST
#切换工作目录
WORKDIR /usr
RUN mkdir /usr/local/java
#ADD 是相对路径jar,把java添加到容器中
ADD jdk-8u171-linux-x64.tar.gz /usr/local/java/
#配置java环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_171
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
ENV PATH $JAVA_HOME/bin:$PATH
(4)执行命令构建镜像
docker build -t=\'jdk1.8\' .
注意后边的空格和点,不要省略
(5)查看镜像是否建立完成
docker images
Docker小结:
7 Docker私有仓库
7.1 私有仓库搭建与配置
(1)拉取私有仓库镜像(此步省略)
docker pull registry
(2)启动私有仓库容器
docker run -di --name=registry -p 5000:5000 registry
(3)打开浏览器 输入地址http://192.168.184.141:5000/v2/_catalog看到{"repositories":[]} 表示私有仓库搭建成功并且内容为空
(4)修改daemon.json
vi /etc/docker/daemon.json
添加以下内容,保存退出。
{"insecure-registries":["192.168.184.141:5000"]}
此步用于让 docker信任私有仓库地址
(5)重启docker 服务
systemctl restart docker
7.2 镜像上传至私有仓库
(1)标记此镜像为私有仓库的镜像
docker tag jdk1.8 192.168.184.141:5000/jdk1.8
(2)再次启动私服容器
docker start registry
(3)上传标记的镜像
docker push 192.168.184.141:5000/jdk1.8
docker 网络
理解docker0
先把所有容器删除: docker rm -f $(docker ps -aq)
再把所有镜像删除: docker rmi -f $(docker images -aq)
清空所有环境!方便学习。
ip addr 查看所有网卡:
三个网络,表示三个不同的环境,那么,docker是怎么处理网络的访问的???
测试:
启动一个容器: docker run -d -P --name tomcat01 tomcat
因为现在是空的docker环境,所以会去重新下载一个tomcat,会有点慢哦~
启动以后进入容器查看会有两个网卡: docker exec -it tomcat01 ip addr
看到eth0:@ifxxx 这么一个ip地址,这就是docker分配的。里面有一个ip地址
Linux 能不能 ping 通这个docker 容器的内部呢??? 肯定是可以的。
那么,在同一个docker里,有几个容器可以互相ping 通吗?肯定也是可以的。
因为docker分配的一个ip,比如是:192.168.0.1,这个0.1是什么意思呢?就是路由器的ip地址,后来的分配就会有0.2,0.3 的地址,都在一个网关里,那么就肯定是可以ping 通的!
我们每启动一个docker容器,docker就会给这个容器分配一个ip,所以我们只要安装了docker,就会有一个docker0
桥接模式,使用的技术是evth-pair技术!这又是什么技术???
在现在这个时候,我们在测试: ip addr
发现又多了一个网卡,那么再 启动一个容器测试,会再多出一个网卡!
我们进入到启动的这个容器查看,会发现网卡是对应的!这就是 evth-pair技术!
意思就是,这个容器带来的网卡,都是一对一对的。
evth-pair 就是一对的虚拟设备接口,它们都是成对出现的。一端连着协议,一段彼此相连。
正因为有这个特性,我们用evth-pair 充当一个桥梁。连接各种虚拟设配。
OpenStac,Docker容器之间的连接,OVS连接,都是用的evth-pair技术!
正常情况: 用evth-pair技术:端口达成协议,直接打通了
画一个网络模型图来理解:
这个图就是说,tomcat01 连接tomcat02 时候,不是直接连的,是通过docker 0 来连接的,这个docker 0 就是相当于一个路由器,先连接tomcat01,然后在路由器里记录这个ip,然后再连接到tomcat02,根本不是直接连到tomcat02 的!
这个网卡是成对出现的,并且也是有规律的!
Docker 的所有网络接口都是虚拟的,因为虚拟的转发效率高!!
只要容器删除,对应的一对网桥也就没了!
Docker网络之 --link
思考问题:
比如就像SpringCloud 的Feign,用名字访问
测试:tomcat02 ping tomcat01 是不能ping 通的。
启动tomcat01 和02 以后:
用 --link
但是 --link 有很大的坑,用tomcat03访问tomcat02 是可以的,但是tomcat02 去ping tomcat03 就是不可以的,它直接改变了hosts 文件,给写死了!!
我们真是开发中是不建议用 --link 的,一点也不灵活!
所以,docker0 的问题就是,容器名连接访问,docker0 不适用,我们要自定义网络!
自定义网络
首先查看所有的网络: docker network ls
我们自己自定义网络也用桥接 模式
首先要知道: 启动命令有这么一个默认的值
自创建一个网络:
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1
--driver 指定网络为bridge桥接模式
--subnet 设置端口,16位的,也就是255*255个
--gateway 设置网关,也等于路由器端口
然后查看一下:
我们自己的网络就创建好了!
它们之间是项目隔离的!
它们也可以用其他技术打通的!--网络连通
网络连通
下图:tomcat-01 去连接tomcat-net-01 那肯定是连不上的,网段都不一样!如果要让tomcat-01 去连接tomcat-net-01
先去让tomcat-01连接mynet
有一个命令,让一个容器去连接一个网络
再查看语法,网络连接,容器,上图的mynet 是定义的网络,tomcat01 是docker0 里的容器
测试连接, docker network connect mynet tomcat01
连接成发现命令执行后没什么反应,可以查看一下mynet网络 docker network inspect mynet
执行命令查找查看:
这时候测试连接,tomcat01 就可以连通了!
实战一个redis 集群
启动六个redis 集群,3个master,3个slave,master网络挂掉以后,slave就顶上去
创建redis网卡: docker network create redis --subnet 172.38.0.0/16
创建成功以后查看网络: docker network ls
查看redis 的具体详细信息: docker network inspect redis
可以看到当前现在是没有一个网络连接的。
要创建6个redis 来测试,太多了,一个一个太麻烦,直接使用脚本来创建:
执行这个脚本命令以后,进入目录,进入redis,查看redis 信息配置
然后一个一个的启动容器
启动后查看
再启动一个:
以此类推启动6个以后,再查看
6 个redis容器都已经启动了,然后创建集群
进入到容器里面: docker exec -it redis-1 /bin/sh
然后进入到了/data 目录,ls 查看发现 aof 文件和 nodes.conf 配置文件
在这里可以创建集群了,执行命令:
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
然后它会自动配置集群
进入集群: redis-cli -c
查看集群信息: cluster info
查看集群节点: cluster nodes
然后测试一下: set a b
把b 这个值set 到了一个master 里
现在让这个主机挂了,看从机是否可以替换上。
新开一个窗口,把13 端口的redis 给停掉:docker stop redis-3
然后再去获取b 的值:get a 这个时候会很慢,因为它需要去分析判断选举,需要一些时间,如果长时间没有相应,就ctrl+c 暂停,再get a 获取
发现是可以获取到的,并看到是从14端口获取到的,这个14端口就是13端口的从机!
这时候执行命令再查看节点: cluster nodes
可以看到,原来的13 端口的master fail 挂掉了,替换成了14 端口成为了master
搭建redis 集群完成!
SpringBoot 项目打包成镜像发布docker
package 打包成一个jar 包
然后打开这个jar 包所在目录cmd 命令执行: java -jar 包名xxxx.jar
本地可以成功,那就是没有问题的了,可以发布了。
可以在idea 上安装一个插件:安装用的最多的那个
安装这个以后可以连接远程仓库,写docker 脚本可以高亮提示,然后就可以写dockerfile 的脚本了
然后可以在docker 上新建一个idea 目录:mkdir idea
把那个dockerfile 文件 和jar 传到虚拟机上,然后就可以执行build 命令发布镜像了
docker build -t wangbiaotest(随便起的镜像名字) .
docker images 查看镜像成功后,运行容器:
docker run -d -P --name wangbiao-springboot wangbiaotest(刚刚瞎起的镜像名字)
然后尝试访问是否成功
查看容器:docker ps
访问本地地址: curl localhost:32779/路径
就ok了
但是如果有很多镜像呢?有100ge镜像,难道都要这样吗??
那就要学Docker Compose 和 Docker Swarm 啦!
Docker Compose
Docker Swarm
和k8s 差不多,但是没有k8s 那么强大。
接下来就是 CI/CD Jenkins 流水线!