Docker基础篇+DockerFile
Docker:您要如何确保应用能够在不同环境中运行和通过质量检测?并且在部署过程中不出现令人头疼的版本、配置问题,也无需重新编写代码和进行故障修复?而这个就是使用容器。Docker解决了运行环境和配置问题的软件容器, 方便做持续集成并有助于整体发布的容器虚拟化技术。
基本概念:
-
仓库(Repository):是存储Docker镜像的地方,可以理解为类似于代码仓库。Docker仓库分为公共仓库和私有仓库两种类型。公共仓库可以免费获取大量的镜像;私有仓库则是企业或个人自己搭建的仓库,用于存储自己的专有镜像。 比如,我们可以使用Docker Hub来搜索并下载已经上传到Docker Hub的镜像,也可以使用Docker搭建私有仓库,将自己的镜像上传并进行管理。
-
镜像(Image):是Docker容器的模板,包含了一组文件系统及其上的应用程序,可以用来创建Docker容器。镜像是只读的,一旦创建就不可修改,可以通过构建、下载或者导入来获取。同一个镜像可以创建多个容器,每个容器都会独立运行。 例如,我们可以使用Docker从某个镜像仓库中下载一个运行Nginx的镜像,然后基于这个镜像创建多个Nginx容器运行不同的Web服务。
-
容器(Container):是Docker中最基本的运行单位,可以将应用程序及其依赖项打包为一个独立的可执行文件,在任何环境中都可以运行。容器之间是相互隔离的,每个容器都拥有自己的文件系统、网络、进程空间等。容器可以被创建、启动、停止、删除等操作。 例如,我们可以使用Docker创建一个运行Web服务的容器,让这个容器在一个独立的环境中运行。
1 从面向对象角度
Docker 利用容器(Container)独立运行的一个或一组应用,应用程序或服务运行在容器里面,容器就类似于一个虚拟化的运行环境,容器是用镜像创建的运行实例。就像是Java中的类和实例对象一样,镜像是静态的定义,容器是镜像运行时的实体。容器为镜像提供了一个标准的和隔离的运行环境,它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台2 从镜像容器角度
可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。 -
实例(Instance):是Docker容器运行时的实例。每个Docker容器都是一个实例,它们有着不同的名称、ID和状态,可以进行启动、停止、删除等操作。 例如,我们通过Docker创建了一个名为"web"的容器,并启动该容器,那么这个"web"容器就是一个实例。
大概流程就是:用户可以从仓库拉取下载需要的镜像,镜像可以用来创建 Docker 容器,然后再通过镜像这个容器模板运行启动容器。
容器与虚拟机比较:比较了 Docker 和传统虚拟化方式的不同之处:
传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;
容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。
每个容器之间互相隔离,每个容器有自己的文件系统 ,容器之间进程不会相互影响,能区分计算资源。
CentOS7安装Docker:
Docker官方安装教程网站:link
1.确定你是CentOS7及以上版本
cat /etc/redhat-release
2.yum安装gcc相关
yum -y install gcc
yum -y install gcc-c++
3.安装需要的软件包
3.1安装docker引擎库:
yum install -y yum-utils
!官网给的是这条命令:yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo。但是是国外的,下载很容易出问题,连接超时。
4.设置stable镜像仓库(用阿里云的)
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
5.更新yum软件包索引
yum makecache fast
6.安装DOCKER CE (开始安装docker引擎)
yum -y install docker-ce docker-ce-cli containerd.io
7.启动docker
systemctl start docker
第一次安装一定要启动docker,然后没返回消息就代表安装成功了。
8.测试
docker version
docker run hello-world
出现hello from docker!代表本机安装成功!
卸载docker命令: (补充知识点,请勿尝试)
1.停止docker
systemctl stop docker
2.移除docker
yum remove docker-ce docker-ce-cli containerd.io
3.删掉docker的文件和第三方包
rm -rf /var/lib/docker
rm -rf /var/lib/containerd
-
阿里云镜像加速:
link
1.注册阿里云账户
2.获得加速器地址连接
2.1 登陆阿里云开发者平台
2.2 点击控制台
2.3 选择容器镜像服务
2.4 获取加速器地址
3.粘贴脚本直接执行
mkdir -p /etc/docker
tee /etc/…………………………去阿里云粘贴自己的,这个只是模板
{
"registry-mirrors": ["https://{自已的编码}.mirror.aliyuncs.com"]
}
4.重启服务器
systemctl daemon-reload
systemctl restart docker
5.启动Docker后台容器(测试运行 hello-world)
docker run hello-world
这个run命令做了啥:
Docker常用命令:
帮助启动类命令:
启动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
查看docker命令帮助文档: docker 具体命令 --help
镜像命令:
各个选项说明:
REPOSITORY:表示镜像的仓库源
TAG:镜像的标签版本号
IMAGE ID:镜像ID
CREATED:镜像创建时间
SIZE:镜像大小
同一仓库源可以有多个 TAG版本,代表这个仓库源的不同个版本,我们使用 REPOSITORY:TAG 来定义不同的镜像。
如果你不指定一个镜像的版本标签,例如你只使用 ubuntu,docker 将默认使用 ubuntu:latest 镜像
OPTIONS说明:
-a :列出本地所有的镜像(含历史映像层)
-q :只显示镜像ID。
命令:docker search [OPTIONS] 镜像名字 (一般下载最前面的那个组织的)
OPTIONS说明:
--limit : 只列出N个镜像,默认25个
docker search --limit 5 redis
docker pull 某个XXX镜像名字 (拉取下载镜像)
docker pull 镜像名字[:TAG]
docker pull 镜像名字
没有TAG就是最新版;等价与docker pull 镜像名字:latest ,例如:docker pull ubuntu
docker system df 查看镜像/容器/数据卷所占的空间
docker rmi 某个XXX镜像名字ID (删除镜像)
删除单个:docker rmi -f 镜像ID
删除多个:docker rmi -f 镜像名1:TAG 镜像名2:TAG
删除全部:docker rmi -f $(docker images -qa)
该配图来自b站up主GeekHour:需要完整命令图可以关注他微信公众号
docker虚悬镜像是什么?
仓库名、标签都是< none >的镜像,俗称虚悬镜像dangling image
容器常用命令:
有镜像才能创建容器, 这是根本前提
先下载一个镜像:docker pull ubuntu
新建+启动容器 :docker run [OPTIONS] IMAGE [COMMAND] [ARG…]
OPTIONS说明(常用):有些是一个减号,有些是两个减号
–name=“容器新名字” 为容器指定一个名称;
-d: 后台运行容器并返回容器ID,也即启动守护式容器(后台运行);
-i:以交互模式运行容器,通常与 -t 同时使用;
-t:为容器重新分配一个伪输入终端,通常与 -i 同时使用;
也即启动交互式容器(前台有伪终端,等待交互);
-P: 随机端口映射,大写P
-p: 指定端口映射,小写p
启动交互式容器(前台命令行): (重点知识)
#使用镜像centos:latest以交互模式启动一个容器,在容器内执行/bin/bash命令。
docker run -it centos /bin/bash
参数说明:
-i: 交互式操作。
-t: 终端。
centos : centos 镜像。
/bin/bash:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 /bin/bash。
要退出终端,直接输入 exit:
列出当前所有正在运行的容器: docker ps [OPTIONS]
OPTIONS说明(常用):
-a :列出当前所有正在运行的容器+历史上运行过的
-l :显示最近创建的容器。
-n:显示最近n个创建的容器。
-q :静默模式,只显示容器编号。
退出容器 :(两种退出方式)
exit:run进去容器,exit退出,容器停止
ctrl+p+q: run进去容器,ctrl+p+q退出,容器不停止
启动已停止运行的容器:docker start 容器ID或者容器名
重启容器:docker restart 容器ID或者容器名
停止容器:docker stop 容器ID或者容器名
强制停止容器:docker kill 容器ID或容器名
删除已停止的容器:docker rm 容器ID
一次性删除多个容器实例:docker rm -f $(docker ps -a -q) / docker ps -a -q | xargs docker rm
启动守护式容器(后台服务器):在大部分的场景下,我们希望 docker 的服务是在后台运行的, 我们可以过 -d 指定容器的后台运行模式。
docker run -d 容器名:#使用镜像centos:latest以后台模式启动一个容器
docker run -d centos
问题:然后docker ps -a 进行查看, 会发现容器已经退出
很重要的要说明的一点: Docker容器后台运行,就必须有一个前台进程.
容器运行的命令如果不是那些一直挂起的命令(比如运行top,tail),就是会自动退出的。
这个是docker的机制问题,比如你的web容器,我们以nginx为例,正常情况下,
我们配置启动服务只需要启动响应的service即可。例如service nginx start
但是,这样做,nginx为后台进程模式运行,就导致docker前台没有运行的应用,…
例如:前台交互式启动: docker run -it redis:6.0.8
后台守护式启动: docker run -d redis:6.0.8
查看容器日志 : docker logs 容器ID
查看容器内运行的进程: docker top 容器ID
查看容器内部细节: docker inspect 容器ID
进入正在运行的容器并以命令行交互:
docker exec -it 容器ID bashShell
重新进入docker attach 容器ID
区别: attach 直接进入容器启动命令的终端,不会启动新的进程 用exit退出,会导致容器的停止。
exec 是在容器中打开新的终端,并且可以启动新的进程 用exit退出,不会导致容器的停止。
推荐使用 docker exec 命令,因为退出容器终端,不会导致容器的停止。
例如:进入redis服务
docker exec -it 容器ID /bin/bash
docker exec -it 容器ID redis-cli
一般用-d后台启动的程序,再用exec进入对应容器实例
从容器内拷贝文件到主机上(容器→主机): 注意这个是文件!
docker cp 容器ID:容器内路径 目的主机路径
导入和导出容器 : 这个是整个容器!
export 导出容器的内容留作为一个tar归档文件[对应import命令]
import 从tar包中的内容创建一个新的文件系统再导入为镜像[对应export]
例如:docker export 容器ID > 文件名.tar
cat 文件名.tar | docker import - 镜像用户/镜像名:镜像版本号
Docker镜像**的加深理解:
镜像是一种轻量级、可执行的独立软件包,它包含运行某个软件所需的所有内容,我们把应用程序和配置依赖打包好形成一个可交付的运行环境(包括代码、运行时需要的库、环境变量和配置文件等),这个打包好的运行环境就是image镜像文件。
只有通过这个镜像文件才能生成Docker容器实例(类似Java中new出来一个对象)。
分层的镜像:
以我们的pull为例,在下载的过程中我们可以看到docker的镜像好像是在一层一层的在下载
UnionFS(联合文件系统):
Docker镜像加载原理:
docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。
bootfs(boot file system)主要包含bootloader和kernel, bootloader主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是引导文件系统bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。
rootfs (root file system) ,在bootfs之上。包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。
为什么 Docker 镜像要采用这种分层结构呢:
镜像分层最大的一个好处就是共享资源,方便复制迁移,就是为了复用。
比如说有多个镜像都从相同的 base 镜像构建而来,那么 Docker Host 只需在磁盘上保存一份 base 镜像;
同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。
重点理解:
Docker镜像层都是只读的,容器层是可写的
当容器启动时,一个新的可写层被加载到镜像的顶部。
这一层通常被称作**“容器层”**,“容器层”之下的都叫“镜像层”。
Docker镜像commit操作案例:
docker commit提交容器副本使之成为一个新的镜像:
docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:[标签名]
例如: 原始的默认Ubuntu镜像是不带着vim命令的,这个时候我们就需要安装Vim:
docker容器内执行上述两条命令:
apt-get update
apt-get -y install vim
安装完成后,commit我们自己的新镜像即可
docker commit -m="add vim cmd" -a="z" 容器id z/myubuntu:1.1
本地镜像发布到阿里云
本地镜像发布到阿里云流程:
1.自己生成个要传的镜像
2.将本地镜像推送到阿里云:
阿里云开发者平台:https://promotion.aliyun.com/ntms/act/kubernetes.html
2.1.创建仓库镜像:
2.1.1 选择控制台,进入容器镜像服务
2.1.2 选择个人实例
2.1.3 命名空间 创建命名空间
2.1.4 仓库名称 创建镜像仓库
2.1.5 进入管理界面获得脚本
2.2.将镜像推送到阿里云
2.2.1 将镜像推送到阿里云registry 管理界面脚本
脚本实例:docker login --username=zzyybuy registry.cn-hangzhou.aliyuncs.com
docker tag cea1bb40441c registry.cn-hangzhou.aliyuncs.com/atguiguwh/myubuntu:1.1
docker push registry.cn-hangzhou.aliyuncs.com/atguiguwh/myubuntu:1.1
上面命令是案例,具体的去阿里云查看具体自己的命令。
3.将阿里云上的镜像下载到本地
例子:docker pull registry.cn-hangzhou.aliyuncs.com/atguiguwh/myubuntu:1.1
本地镜像发布到私有库
Dockerhub、阿里云这样的公共镜像仓库可能不太方便,涉及机密的公司不可能提供镜像给公网,所以需要创建一个本地私人仓库供给团队使用,基于公司内部项目构建镜像。
Docker Registry是官方提供的工具,可以用于构建私有镜像仓库
将本地镜像推送到私有库流程:
1.下载镜像Docker Registry
docker pull registry
2.运行私有库Registry,相当于本地有个私有Docker hub
docker run -d -p 5000:5000 -v /zzyyuse/myregistry/:/tmp/registry --privileged=true registry
默认情况,仓库被创建在容器的/var/lib/registry目录下,建议自行用容器卷映射,方便于宿主机联调
3.案例演示创建一个新镜像,ubuntu安装ifconfig命令
3.1 从Hub上下载ubuntu镜像到本地并成功运行
3.2 原始的Ubuntu镜像是不带着ifconfig命令的
3.3 外网连通的情况下,安装ifconfig命令并测试通过
3.4 安装完成后,commit我们自己的新镜像
docker commit -m="ifconfig cmd add" -a="z" be4779f8w112 zubuntu:1.2
3.5 启动我们的新镜像并和原来的对比
4.curl验证私服库上有什么镜像
curl -XGET http://192.168.111.162:5000/v2/_catalog
可以看到,目前私服库没有任何镜像上传过。。。。。。
5.将新镜像zzyyubuntu:1.2修改符合私服规范的Tag
按照公式: docker tag 镜像:Tag Host:Port/Repository:Tag
自己host主机IP地址,填写你们自己的,不要粘贴错误,O(∩_∩)O
使用命令 docker tag 将zubuntu:1.2 这个镜像修改为192.168.111.162:5000/zubuntu:1.2
docker tag zubuntu:1.2 192.168.111.162:5000/zzyyubuntu:1.2
6.修改配置文件使之支持http
别无脑照着复制,registry-mirrors 配置的是国内阿里提供的镜像加速地址,不用加速的话访问官网的会很慢。
2个配置中间有个逗号 ','别漏了,这个配置是json格式的。
2个配置中间有个逗号 ','别漏了,这个配置是json格式的。
2个配置中间有个逗号 ','别漏了,这个配置是json格式的。vim命令新增如下红色内容:vim /etc/docker/daemon.json
{
“registry-mirrors”: [“https://aa25jngu.mirror.aliyuncs.com”],
“insecure-registries”: [“192.168.111.162:5000”]
}…
修改完后,建议重启docker
7.push推送到私服库
docker push 192.168.111.162:5000/zubuntu:1.2
8.curl验证私服库上有什么镜像
curl -XGET http://192.168.111.162:5000/v2/_catalog
9.pull到本地并运行
docker pull 192.168.111.162:5000/zzyyubuntu:1.2
docker run -it 镜像ID /bin/bash
Docker容器数据卷
坑:容器卷记得加入:–privileged=true
Docker挂载主机目录访问如果出现cannot open directory .: Permission denied
解决办法:在挂载目录后多加一个–privileged=true参数即可
如果是CentOS7安全模块会比之前系统版本加强,不安全的会先禁止,所以目录挂载的情况被默认为不安全的行为,
在SELinux里面挂载目录被禁止掉了额,如果要开启,我们一般使用–privileged=true命令,扩大容器的权限解决挂载目录没有权限的问题,也即
使用该参数,container内的root拥有真正的root权限,否则,container内的root只是外部的一个普通用户权限。
概念:
卷就是目录或文件,存在于一个或多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过Union File System提供一些用于持续存储或共享数据的特性:
卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷
就是将docker容器内的数据保存进宿主机的磁盘中
docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录 镜像名
作用:
将运用与运行的环境打包镜像,run后形成容器实例运行 ,但是我们对数据的要求希望是持久化的
Docker容器产生的数据,如果不备份,那么当容器实例删除后,容器内的数据自然也就没有了。
为了能保存数据在docker中我们使用卷。
特点:
1:数据卷可在容器之间共享或重用数据
2:卷中的更改可以直接实时生效,爽
3:数据卷中的更改不会包含在镜像的更新中
4:数据卷的生命周期一直持续到没有容器使用它为止
案例:
宿主vs容器之间映射添加容器卷
直接命令添加:(将docker容器内的数据保存进宿主机的磁盘中)
docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录 镜像名
例如:
docker run -it --privileged=true -v /tmp/host_data:/tmp/docker_data --name=u1 ubuntu
宿主机下假如没这个目录,会自己帮你创建
查看数据卷是否挂载成功:
docker inspect 容器ID
容器和宿主机之间数据共享:
1 docker修改,主机同步获得
2 主机修改,docker同步获得
3 docker容器stop,主机修改,docker容器重启后依旧可以同步
读写规则映射添加说明
读写(默认) rw = read + write :
docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录:rw 镜像名
只读 :容器实例内部被限制,只能读取不能写 ro = read only :
此时如果宿主机写入内容,可以同步给容器内,容器可以读取到。
docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录:ro 镜像名
卷的继承和共享
容器1完成和宿主机的映射
docker run -it --privileged=true -v /mydocker/u:/tmp --name u1 ubuntu
容器2继承容器1的卷规则
docker run -it --privileged=true --volumes-from 父类 --name u2 ubuntu
例如: docker run -it --privileged=true --volumes-from u1 --name u2 ubuntu
Docker常规安装简介
以后做团队项目,只用去下载仓库或者官网打包好的镜像,直接运行镜像即可使用。步骤也就直接统一了
总体步骤:
- 搜索镜像
- 拉取镜像
- 查看镜像
- 启动镜像 :服务端口映射
- 停止容器
- 移除容器
常见模拟案例:
安装tomcat
1.docker hub上面查找tomcat镜像
docker search tomcat
2.从docker hub上拉取tomcat镜像到本地
docker pull tomcat
3.docker images查看是否有拉取到的tomcat
4.使用tomcat镜像创建容器实例(也叫运行镜像)
docker run -it -p 8080:8080 tomcat
- -p 小写,主机端口:docker容器端口
- -P 大写,随机分配端口
- i:交互
- t:终端
- d:后台
5.访问猫首页
出现问题:出现404,访问不到
解决:1.可能没有映射端口或者没有关闭防火墙
2.先把webapps文件删了,再把webapps.dist目录换成webapps。因为真正有东西的在webapps.dist里面,所以把它进行改名
先把webapps文件删了: rm -f webapps
把webapps.dist目录换成webapps mv webapps.dist webapps
这样子运行最新版都要修改,太麻烦了。可以使用免修版:
免修改版说明:
docker pull billygoo/tomcat8-jdk8
docker run -d -p 8080:8080 --name mytomcat8 billygoo/tomcat8-jdk8
安装mysql
1.docker hub上面查找mysql镜像
2.从docker hub上(阿里云加速器)拉取mysql镜像到本地标签为5.7
3.使用mysql5.7镜像创建容器(也叫运行镜像)
简单版:
使用mysql镜像
docker run -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
docker ps
docker exec -it 容器ID /bin/bash
mysql -uroot -p
尝试建库建表插入数据:
show databases;
create database db01;
create table t1(id int,name varchar(20));
insert into t1 values(1,'z3');
select * from t1;
去使用本地的navicat看看能不能连接运行在dokcer上的mysql容器实例服务,发现是可以的,且刚刚新建的表和数据都存在。在navicat中插入数据发现也是互通的。
坑:但是插入中文数据时,出现了报错:
说明docker上默认字符集编码隐患 ,于是乎在docker里面的mysql容器实例查看,输入命令内容如下:
SHOW VARIABLES LIKE 'character%'
发现全是拉丁,这种得在docker的mysql实例修改!
且一不小心删除容器后,那里面的mysql数据如何办?
看下面的实战版↓:
实战版(解决乱码和备份问题):
1.新建mysql容器实例
docker run -d -p 3306:3306 --privileged=true
-v /zzyyuse/mysql/log:/var/log/mysql
-v /zzyyuse/mysql/data:/var/lib/mysql
-v /zzyyuse/mysql/conf:/etc/mysql/conf.d
-e MYSQL_ROOT_PASSWORD=123456 --name mysql mysql:5.7
2. 解决中文乱码问题:新建my.cnf 通过容器卷同步给mysql容器实例
[client]
default_character_set=utf8
[mysqld]
collation_server = utf8_general_ci
character_set_server = utf8
3.重新启动mysql容器实例再重新进入并查看字符编码
4.再新建库新建表再插入中文测试
5.结论:
之前的DB 无效
修改字符集操作+重启mysql容器实例
之后的DB 有效,需要新建
结论:docker安装完MySQL并run出容器后,建议请先修改完字符集编码后再新建mysql库-表-插数据
6.假如将当前容器实例删除,再重新来一次,之前建的db01实例还有,里面的数据也没有丢失
docker run -d -p 3306:3306 --privileged=true
-v /zzyyuse/mysql/log:/var/log/mysql
-v /zzyyuse/mysql/data:/var/lib/mysql
-v /zzyyuse/mysql/conf:/etc/mysql/conf.d
-e MYSQL_ROOT_PASSWORD=123456 --name mysql mysql:5.7
以后,务必要注意解决乱码和备份问题!
安装redis
1.从docker hub上(阿里云加速器)拉取redis镜像到本地标签为6.0.8
2.命令提醒:容器卷记得加入–privileged=true
Docker挂载主机目录Docker访问出现cannot open directory .: Permission denied
解决办法:在挂载目录后多加一个--privileged=true参数即可
3.在CentOS宿主机下新建目录/app/redis
mkdir -p /app/redis
4.将一个redis.conf文件模板拷贝进/app/redis目录下
4.1拷贝配置文件:
将准备好的redis.conf文件放进/app/redis目录下
这个看之前的Linux安装redis的详细教程:
5./app/redis目录下修改redis.conf文件
3.4开启redis数据持久化 appendonly yes 可选
6.使用redis6.0.8镜像创建容器(也叫运行镜像)
7.测试redis-cli连接上来
8.请证明docker启动使用了我们自己指定的配置文件
- 修改前:我们用的配置文件,数据库默认是16个
- 修改后:宿主机的修改会同步给docker容器里面的配置。 记得重启服务
9.测试redis-cli连接上来第2次
DockerFile解析
Dockerfile是用来构建Docker镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本
使用目的:使用基本命令很麻烦,每一次要变化的时候,都需要commit;假如有很多内容要提交,那要commit很多次,而DockerFile可以一次性搞定,它就像列了一个清单,你后续需要加入任何功能,直接在清单中写好,直接就相等于多次提交了。
构建三步骤:
1.编写Dockerfile文件
2.docker build命令构建镜像
3.docker run依镜像运行容器实例
Dockerfile内容基础知识:
1:每条保留字指令都必须为大写字母且后面要跟随至少一个参数
2:指令按照从上到下,顺序执行
3:#表示注释
4:每条指令都会创建一个新的镜像层并对镜像进行提交
Docker执行Dockerfile的大致流程:
(1)docker从基础镜像运行一个容器
(2)执行一条指令并对容器作出修改
(3)执行类似docker commit的操作提交一个新的镜像层
(4)docker再基于刚提交的镜像运行一个新容器
(5)执行dockerfile中的下一条指令直到所有指令都执行完成
DockerFile常用保留字指令
可以参考tomcat8的dockerfile入门:https://github.com/docker-library/tomcat
保留字:
FROM :基础镜像,当前新镜像是基于哪个镜像的,指定一个已经存在的镜像作为模板,第一条必须是from
MAINTAINER:镜像维护者的姓名和邮箱地址
RUN:容器构建时需要运行的命令
两种格式:
shell格式: RUN yum -y install vim
exec格式: RUN ["可执行文件","参数1","参数2"]
推荐使用shell格式,好理解和好用点
RUN是在 docker build时运行
EXPOSE:当前容器对外暴露出的端口
WORKDIR: 指定在创建容器后,终端默认登陆的进来工作目录,一个落脚点
USER: 指定该镜像以什么样的用户去执行,如果都不指定,默认是root
ENV:用来在构建镜像过程中设置环境变量
ENV MY_PATH /usr/mytest
这个环境变量可以在后续的任何RUN指令中使用,这就如同在命令前面指定了环境变量前缀一样;
也可以在其它指令中直接使用这些环境变量,
比如:WORKDIR $MY_PATH
ADD:将宿主机目录下的文件拷贝进镜像且会自动处理URL和解压tar压缩包
COPY:类似ADD,拷贝文件和目录到镜像中。 将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置
COPY src dest
COPY ["src", "dest"]
<src源路径>:源文件或者源目录
<dest目标路径>:容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。
VOLUME: 容器数据卷,用于数据保存和持久化工作
CMD: 指定容器启动后的要干的事情
!注意:Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换
比如:在tomcat的dockerFile 最后一行是: CMD ["catalina.sh","run"]
但是你在docker run这个命令后面加一个/bin/bash ,虽然成功启动了,但是相当于在DockerFile后面又加了一个CMD ["/bin/bash","run"];会导致前面的CMD被覆盖了。这个时候去浏览器就看不到猫了。
它和前面RUN命令的区别:
- CMD是在docker run 时运行。
- RUN是在 docker build时运行。
ENTRYPOINT :类似于 CMD 指令,但是ENTRYPOINT不会被docker run后面的命令覆盖, 而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序
命令格式和案例说明:
命令格式:ENTRYPOINT ["<executeable>","<param1>","<param2>",...]
ENTRYPOINT可以和CMD一起用,一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参。
当指定了ENTRYPOINT后,CMD的含义就发生了变化,不再是直接运行其命令而是将CMD的内容作为参数传递给ENTRYPOINT指令,他两个组合会变成 <ENTRTPOINT>"<CMD>"
案例如下:假设已通过 Dockerfile 构建了 nginx:test 镜像:
FROM nginx
ENTRYPOINT ["nginx","-c"] # 定参
CMD ["etc/nginx/nginx.conf"] #变参
是否传参 | 按照dockerfile编写执行 | 传参运行 |
---|---|---|
Docker命令 | docker run nginx:test | docker run nginx:test -c /etc/nginx/new.conf |
衍生出的实际命令 | nginx -c /etc/nginx/nginx.conf | nginx -c /etc/nginx/new.conf |
优点:在执行docker run的时候可以指定 ENTRYPOINT 运行所需的参数。
注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。
案例,加强理解:
自定义镜像mycentosjava8
1.要求: Centos7镜像具备 vim+ifconfig+jdk8 这三个功能
JDK的下载镜像地址:下载地址:https://www.oracle.com/java/technologies/downloads/#java8
2.编写 准备编写Dockerfile文件 大写字母D
FROM centos
MAINTAINER z
ENV MYPATH /usr/local
WORKDIR $MYPATH
#安装vim编辑器
RUN yum -y install vim
#安装ifconfig命令查看网络IP
RUN yum -y install net-tools...
#安装Java8及lib库
RUN yun -y install glibc.1686
RUN mkdir /usr/local/java
#ADD 是相对路径jar,把jdk-8u171-inux-x64.tar.gz添加到容器中,安装包必须要和Dockerfile文件在同一位置 自己复制自己所下载jdk的名字
ADD idk- 8u171- linux- x64.tar.gz /usr/local/java/
#配置java环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0171
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
EXPOSE 80
CMD echo $MYPATH
CMD echo "success------------------------ok"
CMD /bin/bash
3.构建
docker build -t 新镜像名字:TAG .
如:docker build -t centosjava8:1.5 .
注意,上面TAG后面有个空格,有个点
4.运行
docker run -it 新镜像名字:TAG
docker run -it centosjava8:1.5 /bin/bash
虚悬镜像
仓库名、标签都是的镜像,俗称dangling image
1.Dockerfile写一个:
1 vim Dockerfile
from ubuntu
CMD echo 'action is success'
2 docker build .
2.查看
docker image ls -f dangling=true
3.删除
docker image prune
虚悬镜像已经失去存在价值,有就可以删除
Docker微服务实战
通过dockerfile发布微服务部署到docker容器:
1.IDEA工具里面搞定微服务jar包 : docker_boot-0.0.1-SNAPSHOT.jar
2.编写Dockerfile
# 基础镜像使用java
FROM java:8
# 作者
MAINTAINER z
# VOLUME 指定临时文件目录为/tmp,在主机/var/lib/docker目录下创建了一个临时文件并链接到容器的/tmp
VOLUME /tmp
# 将jar包添加到容器中并更名为z_docker.jar
ADD docker_boot-0.0.1-SNAPSHOT.jar z_docker.jar
# 运行jar包
RUN bash -c 'touch /z_docker.jar'
ENTRYPOINT ["java","-jar","/z_docker.jar"]
#暴露6001端口作为微服务
EXPOSE 6001
记得将微服务jar包和Dockerfile文件上传到同一个目录下/mydocker:
jar传到/mydocker下面,在/mydocker下面vim Dockerfile
3.构建镜像
docker build -t z_docker:1.6 .
打包成镜像文件
4.运行容器 (注意:run后面也不要加内容了,以免命令覆盖)
docker run -d -p 6001:6001 z_docker:1.6
5.访问测试