目录
1 Docker介绍
- 宿主机:安装Docker守护进程的Linux服务器
- 镜像(Image):Docker 镜像,就相当于是一个 root 文件系统
- 容器(Container):镜像运行之后的实体,镜像和容器的关系,就像是面向对象程序设计中的类和对象一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
- 仓库(Repository):保存镜像。
2 Docker安装启动
2.1 Docker安装
可以直接使用现成的镜像,也可以找一个原始的CentOS镜像(7及以上版本),然后自己从头到尾下载一遍:
(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 Docker 守护进程相关指令
- 启动docker:systemctl start docker
- 停止docker:systemctl stop docker
- 重启docker:systemctl restart docker
- 查看docker状态:systemctl status docker
- 开机启动:systemctl enable docker
- 查看docker概要信息:docker info
- 帮助文档:docker --help
2.3 Docker 镜像加速
这个功能我暂时还没用过。
- 编辑该文件: vim /etc/docker/daemon.json 在该文件中输入如下内容:
{
"registry-mirrors": ["https://3ad96kxd.mirror.aliyuncs.com"]
}
这个镜像仓库如果不能用,可以自己从阿里云上申请 ,必须要注册,会为每个人分配一个免费的docker镜像加速地址 。
- 配置完成后刷新配置
sudo systemctl daemon-reload
sudo systemctl restart docker
3 Docker命令
3.1 镜像命令
- 查看本地所有镜像:docker images
- 从远端搜索镜像:docker search 镜像名称
- 拉取镜像:docker pull 镜像名称(如拉取centos7镜像:docker pull centos:7)
- 删除镜像:docker rmi 镜像id/镜像名称(docker rmi 58ef746a6030 或 docker rmi tomcat:7)
3.2 容器命令
- 查看正在运行的容器:docker ps
- 查看所有容器:docker ps -a
- 创建并启动容器(详情如下):docker run 参数
- 登录容器:docker exec -it 容器名称 (或者容器ID) /bin/bash
- 容器的启动与停止:docker start 容器名称(或者容器ID)、docker stop 容器名称
- 文件拷贝(详情如下):docker cp
- 查看容器信息:docker inspect 容器名称(容器ID)
- 删除容器(正在运行的无法删除):docker rm 容器名称(容器ID)
1、创建容器举例(重要):
使用镜像centos7创建交互式容器(创建完之后直接进入容器的命令行中,退出容器则容器关闭)
注意:最后面那个“bin/bash”指令一般只有CentOS系统才会去执行,而tomcat、mysql、redis这些容器是不需要执行这个指令的!
docker run -it --name=c1 centos:7 /bin/bash
使用镜像centos7创建守护式容器(创建完之后还停留在宿主机命令行中,容器已经在后台启动)
docker run -id --name=c2 centos:7 /bin/bash
2、创建容器时常用的命令参数(重要):
-i:表示运行容器
-t:表示容器启动后会进入其命令行。加入这两个参数后,容器创建就能登录进去。
-d:在run后面加上-d参数,则会创建一个守护式容器在后台运行(这样创建容器后不会自动登录容器)。
--name :为创建的容器命名。
-v:表示目录映射关系(前者是宿主机目录,后者是映射到宿主机上的目录),可以使用多个-v做多个目录或文件映射。注意:最好做目录映射,在宿主机上做修改,然后共享到容器上。
-p:表示端口映射,前者是宿主机端口,后者是容器内的映射端口。可以使用多个-p做多个端口映射
-ti:创建交互式容器,创建容器后自动进入容器,退出容器后容器自动关闭(可理解为关机)
-di:创建守护式容器,创建一个容器在后台运行,需要使用docker exec 进入容器,退出后容器不会关闭。
进入容器之后,初始化执行的命令:/bin/bash
3、文件拷贝举例
文件拷贝(容器到宿主机):docker cp 容器名称:容器目录 需要拷贝的文件或目录
把文件从c1“/”路径下的“a.txt文件”拷贝到宿主机的中的的“/root/”路径下:
docker cp c1:/a.txt /root/
文件拷贝(宿主机到容器):docker cp 需要拷贝的文件或目录 容器名称:容器目录
把文件"b.txt" 从宿主机的“/root/”路径下拷贝到容器c1的“/root/” 路径下:
docker cp /root/b.txt c1:/root/
4 Dcoker 数据卷
4.1 数据卷概述
数据卷就是宿主机中的一个目录或一个文件,数据卷的作用如下:
- 容器数据持久化,即使容器被删除了,数据卷还在
- 客户端和容器进行数据交换
- 容器之间进行数据交换
4.2 数据卷配置
容器挂载数据卷,实际上就是确定宿主机中文件夹和容器中文件夹中的对应关系,这种关系可以是一对一,也可以是一对多,也可以是多对一。
情况1:一个容器挂载一个数据卷(重要)
以“创建完不进入容器命令行”的方式创建容器c1(centos:7),
宿主机的文件夹路径为“/root/host_data1”,
容器文件夹的位置为:“/root/c1_data”
docker run -di --name=c1 -v /root/host_data1:/root/c1_data centos:7 /bin/bash
情况2:一个容器挂载多个数据卷(容器-宿主机路径两两对应即可)
docker run -di --name=c1 -v /root/host_data1:/root/c1_data1 -v /root/host_data2:/root/c1_data2 centos:7 /bin/bash
情况3:多个容器挂载一个数据卷
比较笨的写法是:只要把“一个容器挂载一个数据卷”的代码多写几遍就可以了,如下:
docker run -di --name=c2 -v /root/host_data_common:/root/c2_data centos:7
docker run -di --name=c3 -v /root/host_data_common:/root/c3_data centos:7
既然那个数据卷已经固定了,那么每次创建容器的时候就没必要总去把那个数据卷的绝对路径写出了!
于是我们可以将容器c3作为一个数据卷容器,让c3去挂载宿主机中的数据卷,然后c1、c2可分别挂在到c3上,实现了c1、c2间接挂载数据卷的目的。如下图:
具体步骤:
(1)先创建容器c3,作为数据卷容器,挂载宿主机
docker run -di --name=c3 -v /root/host_data1:/root/c3_data centos:7
(2)再创建容器c1,挂载数据卷容器c3
docker run -di --name=c1 --volumes-from c3 centos:7
(3)再创建容器c2,挂载数据卷容器c3
docker run -di --name=c2 --volumes-from c3 centos:7
注意:在创建容器c1、c2的时候并没有指定c1、c2用于挂载c3所对应的文件目录,但是由于c3在挂载的时候已经指定好了具体要挂载宿主机所对应的目录,那么容器c1、c2在同样的目录下就自动创建了对应的文件目录!
5 Dcoker中部署应用
5.1 Mysql部署
- 搜索mysql镜像
docker search mysql
- 拉取mysql镜像(镜像具体的标签号可以去DockerHub搜索)
docker pull mysql:5.6
- 创建容器,设置端口映射、目录映射
docker run -di --name=c_mysql -p 3307:3306 -v /root/mysql/logs:/logs -v /root/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:5.6
参数说明:
-p 3307:3306:将容器的 3306 端口映射到宿主机的 3307 端口。 |
-v /root/mysql/logs:/logs:将主机目录(/root/mysql)下的 logs 目录挂载到容器中的 /logs 日志目录 |
-v /root/mysql/data:/var/lib/mysql :将主机目录(/root/mysql)下的data目录挂载到容器的 /var/lib/mysql 数据目录 |
-e MYSQL_ROOT_PASSWORD=123456:初始化 root 用户的密码。 |
- 进入容器,操作mysql
docker exec –it c_mysql /bin/bash
mysql -uroot -p123456
- 使用Navicat连接容器中的mysql
ip:宿主机ip
端口:宿主机的端口号,该端口号和容器端口号形成了映射
5.2 Tomcat部署
- 搜索tomcat镜像
docker search tomcat
- 拉取tomcat镜像
docker pull tomcat:8-jdk8
- 创建容器、设置端口映射
docker run -id --name=c_tomcat -p 8080:8080 -v /root/tomcat/webapps:/usr/local/tomcat/webapps tomcat:8-jdk8
参数说明:
-p 8080:8080:将容器的8080端口映射到主机的8080端口 |
-v /root/tomcat/webapps:/usr/local/tomcat/webapps:将主机目录(/root/tomcat/webapps)挂载到容器的webapps |
- 向Tomcat中部署服务,使用FinalShell文件上传
- 使用外部机器访问Tomcat,测试部署服务
注意:SpringBoot开发的项目只能部署在8及以上版本的Tomcat上,7不可以!
5.3 Redis部署
- 搜索redis镜像
docker search redis
- 拉取redis镜像
docker pull redis:5.0
- 创建容器,设置端口映射(这里没有指定数据卷 -v)
docker run -id --name=c_redis -p 6379:6379 redis:5.0
- 外部连接redis,测试
6 制作Docker镜像
6.1 镜像的备份与迁移
需求:
- 在一个原始镜像的基础上构造一个容器出来(同启动容器的操作,不用另外再做)
- 以这个容器为基础进行一系列操作后把这个新容器转换为一个新的镜像(旧的容器和镜像可以删掉,以免影响)
- 把这个新的镜像打成压缩包
- 把压缩包导入成新的本地镜像
- 使用新导入的镜像
- 本地容器转镜像:将正在运行的容器c_tomcat保存为镜像my_tomcat:1.0
docker commit c_tomcat my_tomcat:1.0
- 镜像转tar压缩包:将my_tomcat:1.0这个镜像保存为my_tomcat.tar压缩包,保存位置就是当前路径下
docker save -o my_tomcat.tar my_tomcat:1.0
- 把压缩包导入成新的本地镜像(先删除掉原来的容器和镜像,不要受其干扰):将新获取到的my_tomcat.tar压缩包转为本地镜像
docker load -i my_tomcat.tar
- 使用新的镜像:和启动容器的操作指令完全一样,新的镜像及其整套运行环境和原来的一摸一样!一次构建,多次运行!
docker run -di --name=new_tomcat -p 8080:8080 -v /root/tomcat/webapps/:/usr/local/tomcat/webapps my_tomcat:1.0
上述内容其实做的是一件事:把一个容器转成镜像,再把镜像打包,打包后的镜像传给谁都可以,然后另外一个人获取到该压缩包后把该镜像导入到本地的镜像仓库中,最后使用新的镜像。
说白了就是把一个镜像从一个地方搬运到另一个地方而已。
这里“被搬运”的镜像是一个体积较大的压缩包,因为我们搬运的是个上层镜像,该镜像以若干个基础镜像为基础所构建(例如:tomcat基于jdk,jdk基于rootfs,rootfs基于bootfs)。
即:上述的方法让我们“抱着一块大石头”在进行转移,那么是否可以减小镜像迁移过程中镜像文件体积呢?DockerFile出现了!
6.2 DockerFile
(1)DockerFile介绍
- 一个文本文件
- 包含了一条条的指令
- 基于基础镜像每一条指令构建一层,最终构建出一个新的镜像
- DockerFile 关键字介绍
关键字 | 作用 | 备注 |
FROM | 指定父镜像 | 指定dockerfile基于哪个image构建 |
MAINTAINER | 作者信息 | 用来标明这个dockerfile谁写的 |
LABEL | 标签 | 用来标明dockerfile的标签 可以使用Label代替Maintainer 最终都是在docker image基本信息中可以查看 |
RUN | 执行命令 | 执行一段命令 默认是/bin/sh 格式: RUN command 或者 RUN ["command" , "param1","param2"] |
CMD | 容器启动命令 | 提供启动容器时候的默认命令 和ENTRYPOINT配合使用.格式 CMD command param1 param2 或者 CMD ["command" , "param1","param2"] |
ENTRYPOINT | 入口 | 一般在制作一些执行就关闭的容器中会使用 |
COPY | 复制文件 | build的时候复制文件到image中 |
ADD | 添加文件 | build的时候添加文件到image中 不仅仅局限于当前build上下文 可以来源于远程服务 |
ENV | 环境变量 | 指定build时候的环境变量 可以在启动的容器的时候 通过-e覆盖 格式ENV name=value |
ARG | 构建参数 | 构建参数 只在构建的时候使用的参数 如果有ENV 那么ENV的相同名字的值始终覆盖arg的参数 |
VOLUME | 定义外部可以挂载的数据卷 | 指定build的image那些目录可以启动的时候挂载到文件系统中 启动容器的时候使用 -v 绑定 格式 VOLUME ["目录"] |
EXPOSE | 暴露端口 | 定义容器运行的时候监听的端口 启动容器的使用-p来绑定暴露端口 格式: EXPOSE 8080 或者 EXPOSE 8080/udp |
WORKDIR | 工作目录 | 指定容器内部的工作目录 如果没有创建则自动创建 如果指定/ 使用的是绝对地址 如果不是/开头那么是在上一条workdir的路径的相对路径 |
USER | 指定执行用户 | 指定build或者启动的时候 用户 在RUN CMD ENTRYPONT执行的时候的用户 |
HEALTHCHECK | 健康检查 | 指定监测当前容器的健康监测的命令 基本上没用 因为很多时候 应用本身有健康监测机制 |
ONBUILD | 触发器 | 当存在ONBUILD关键字的镜像作为基础镜像的时候 当执行FROM完成之后 会执行 ONBUILD的命令 但是不影响当前镜像 用处也不怎么大 |
STOPSIGNAL | 发送信号量到宿主机 | 该STOPSIGNAL指令设置将发送到容器的系统调用信号以退出。 |
SHELL | 指定执行脚本的shell | 指定RUN CMD ENTRYPOINT 执行命令的时候 使用的shell |
(2)DockerFile对于不同角色的作用
- 开发:可以为开发团队提供一个完全一致的开发环境
- 测试:可以直接拿开发时所构建的镜像或者通过Dockerfile文件构建一个新的镜像
- 运维:在部署时,可以实现应用的无缝移植
(3)DockerFile案例
需求:定义dockerfile,发布springboot项目
步骤
- 在IDEA中编辑Dockerfile文件(在本地电脑进行),编辑完之后把这个Dockerfile文件以及一个springboot项目的jar包文件(xxx.jar)拷贝到宿主机的root目录下(直接拖进去)
- 定义基础镜像
- 定义作者信息
- 向镜像中添加jar包文件
- 定义当前镜像启动容器时,执行命令
Dockerfile文件内容如下:
#定义基础父镜像的名称、版本
FROM java:8
#作者信息
MAINTAINER lmy <798511784@qq.com>
#向当前镜像中添加文件(将本地文件springboot.jar 传到镜像中并命令为app.jar)
ADD springboot.jar app.jar
#定义当前的镜像在创建容器后所执行的命令
CMD java -jar app.jar
两个文件从Windows本地机器拷贝到VMware中的宿主机中的目录展示如下图:
- 在宿主机中(注意路径),构建镜像,用到docker命令(在宿主机中进行,本来这一步也是可以在本地电脑IDEA中完成的(前提是本地电脑要装Docker),但是因为本地电脑一旦安装了vmware就不能再安装Docker了,所以才在宿主机中构建)
#构建镜像:镜像基于文件当前路径下的Dockerfile文件,构建好的镜像名字和版本号为:springboot:2.0 构建好的镜像文件压缩包的位置就是当前路径下
docker build -f Dockerfile -t springboot:2.0 ./
- 基于镜像,启动容器(这里启动方式用的是ti,即交互式容器,一启动就直接能看到springboot的启动过程,这里只是为了可视化展示,但实际用di更好,不然的话没法进行别的操作了)
docker run -ti --name=c_springboot -p 9999:8080 springboot:2.0
- 测试
上述步骤做的事情其实和6.1小节做的是事情是一样的,之前构建镜像借助于一个大的镜像压缩包
而现在只需要一个用于描述该镜像的Dockerfile文件、以及一个只有很小体积的springboot项目的jar包文件(10几MB)就能直接生成该springboot项目的镜像(6.1中是一个tomcat镜像,但道理是相同的)
7 搭建Docker私有仓库
Docker hub(https://hub.docker.com)是一个用于管理公共镜像的仓库,可推送和拉取镜像。
但是,有时候我们的服务器无法访问互联网,或者你不希望将自己的镜像放到公网当中,
于是就需要搭建自己的私有仓库来存储和管理自己的镜像
7.1 搭建私有仓库
注意:本来私有仓库应该部署单独服务器进行搭建,这里为了方便就也搭建在本地电脑上了。
- 拉取私有仓库镜像
docker pull registry
- 启动私有仓库容器
docker run -di --name=my_registry -p 5000:5000 registry:latest
- 测试私有镜像仓库是否搭建成功
#ip换成自己的用于部署私有仓库的ip(这里用的是docker宿主机ip)
打开浏览器 输入地址 http://192.168.1.171:5000/v2/_catalog
看到{"repositories":[]} 表示私有仓库搭建成功
- 配置私有仓库(让你本地电脑的Docker连接上远程的私有仓库,这里为了演示私有仓库也在本地嘿嘿)
# 修改daemon.json
vim /etc/docker/daemon.json
# 在上述文件中添加一个key,保存退出
# 此步用于让 docker 信任私有仓库地址
{
"insecure-registries":["私有仓库服务器ip:5000"]
}
- 重启Docker服务
systemctl restart docker
docker start my_registry
7.2 镜像上传私有仓库
(1)标记镜像为私有仓库的镜像
# docker tag {镜像名称:标签} {私有仓库host:port}/{私有镜像仓库中的名称:标签}
docker tag springboot:2.0 192.168.1.171:5000/springboot:2.0
(2)上传标记的镜像
# docker push {私有仓库host:port}/{私有镜像仓库中的名称:标签}
docker push 192.168.1.171:5000/springboot:2.0
7.3 从私有仓库拉取镜像
docker pull {私有仓库host:port}/{私有镜像仓库中的名称:标签}
docker pull 192.168.1.171:5000/springboot:2.0