docker简介
docker是什么?
问题:为什么会有docker的出现
一款产品从开发到上线,需要重复地配置环境和部署,对于开发和运维都不得不面对版本的迭代环境的兼容等问题,而docker镜像的设计,使得我们得以打破过去「程序即应用」的观念。透过镜像(images)将作业系统核心除外,运作应用程式所需要的系统环境,由下而上打包,达到应用程式跨平台间的无缝接轨运作。
docker的设计理念
docker的主要目标是“Build,Ship and Run Any App,Anywhere”,也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理,使用户的APP(可以是一个WEB应用或数据库应用等等)及其运行环境能够做到“一次封装,到处运行”。Linux 容器技术的出现就解决了这样一个问题,而 docker 就是在它的基础上发展过来的。将应用运行在docker 容器上面,而 docker 容器在任何操作系统上都是一致的,这就实现了跨平台、跨服务器。只需要一次配置好环境,换到别的机子上就可以一键部署好,大大简化了操作。
总结
docker是一种解决了运行环境和配置问题的软件容器,方便做持续集成并有助于整体发布的容器虚拟化技术。
docker能干什么
虚拟机技术
虚拟机(virtual machine)就是带环境安装的一种解决方案。它可以在一种操作系统里面运行另一种操作系统,比如在Windows 系统里面运行Linux 系统。应用程序对此毫无感知,因为虚拟机看上去跟真实系统一模一样,而对于底层系统来说,虚拟机就是一个普通文件,不需要了就删掉,对其他部分毫无影响。这类虚拟机完美的运行了另一套系统,能够使应用程序,操作系统和硬件三者之间的逻辑不变。
虚拟机的缺点:1 资源占用多 2 冗余步骤多 3 启动慢
容器虚拟化技术
由于前面虚拟机存在这些缺点,Linux 发展出了另一种虚拟化技术:Linux 容器(Linux Containers,缩写为 LXC)。Linux 容器不是模拟一个完整的操作系统,而是对进程进行隔离。有了容器,就可以将软件运行所需的所有资源打包到一个隔离的容器中。容器与虚拟机不同,不需要捆绑一整套操作系统,只需要软件工作所需的库资源和设置。系统因此而变得高效轻量并保证部署在任何环境中的软件都能始终如一地运行。 比较了 docker 和传统虚拟化方式的不同之处:传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。 每个容器之间互相隔离,每个容器有自己的文件系统 ,容器之间进程不会相互影响,能区分计算资源。
一次构建、随处运行
- 更快速的应用交付和部署
- 更便捷的升级和扩缩容
- 更简单的系统运维
- 更高效的计算资源利用
docker的安装
安装docker ce(社区版)
安装Docker的依赖库。
yum install -y yum-utils device-mapper-persistent-data lvm2
添加Docker CE的软件源信息。
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
安装Docker CE。
yum makecache fast
yum -y install docker-ce
- 启动Docker服务。
systemctl start docker
配置阿里云镜像加速
创建/etc/docker/daemo.json
,写入以下命令。
{
"registry-mirrors": ["https://kqh8****.mirror.aliyuncs.com"]
}
重新加载服务配置文件。
systemctl daemon-reload
重启Docker服务。
systemctl restart docker
测试docker的hello-world容器
拉取hello-world
容器
docker pull hello-world
查看执行以下命令查看是否拉取成功
docker images
执行hello-world容器
docekr run hello-world
若页面上打印Hello from Docker!
以及其他的一些提示语句说明docker正常安装
docker底层原理
docker是怎样工作的
Docker是一个Client-Server结构的系统,Docker守护进程运行在主机上, 然后通过Socket连接从客户端访问,守护进程从客户端接受命令并管理运行在主机上的容器。 容器,是一个运行时环境,就是我们前面说到的集装箱。
为什么docker比虚拟机快
- docker有着比虚拟机更少的抽象层。由于docker不需要Hypervisor实现硬件资源虚拟化,运行在docker容器上的程序直接使用的都是实际物理机的硬件资源。因此在CPU、内存利用率上docker将会在效率上有明显优势。
- docker利用的是宿主机的内核,而不需要Guest OS。因此,当新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核。仍而避免引寻、加载操作系统内核返个比较费时费资源的过程,当新建一个虚拟机时,虚拟机软件需要加载Guest OS,返个新建过程是分钟级别的。而docker由于直接利用宿主机的操作系统,则省略了返个过程,因此新建一个docker容器只需要几秒钟。
docker常用命令
帮助命令
查看docker版本
docker version
查看docker详细信息
docker info
docker 帮助命名
docker --help
docker 镜像命令
列出本地主机上的镜像
docker images [options]
options说明
- -a :列出本地所有的镜像(含中间映像层)
- -q :只显示镜像ID。
- –digests :显示镜像的摘要信息
- –no-trunc :显示完整的镜像信息
执行结果说明
- REPOSITORY:表示镜像的仓库源
- TAG:镜像的标签
- IMAGE ID:镜像ID
- CREATED:镜像创建时间
- SIZE:镜像大小
同一仓库源可以有多个 TAG,代表这个仓库源的不同个版本,我们使用 REPOSITORY:TAG 来定义不同的镜像。如果你不指定一个镜像的版本标签,例如你只使用 ubuntu,docker 将默认使用 ubuntu:latest 镜像
查找镜像
docker search [options] docker-name
options说明
- –no-trunc : 显示完整的镜像描述
- -s number : 列出收藏数不小于指定值的镜像。
- –automated : 只列出 automated build类型的镜像;
下载镜像
docker pull docerk-name/docker-id[:tag]
[:tag]代表docker镜像的版本,不加则默认为最新版
删除单个镜像
docker rmi [-f] docker docker-id
加-f代表强制删除
删除多个镜像
docker rmi -f 镜像名1:TAG 镜像名2:TAG
删除全部镜像
docker rmi -f $(docker images -qa)
容器命令
新建并启动容器
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
OPTIONS说明(常用):有些是一个减号,有些是两个减号
- –name=“容器新名字”: 为容器指定一个名称;
- -d: 后台运行容器,并返回容器ID,也即启动守护式容器;
- -i:以交互模式运行容器,通常与 -t 同时使用;
- -t:为容器重新分配一个伪输入终端,通常与 -i 同时使用;
- -P: 随机端口映射;
- -p: 指定端口映射,有以下四种格式 :ip:hostPort:containerPort 、 ip::containerPort、hostPort:containerPort 、containerPort
列出当前所有正在运行的容器
docker ps [OPTIONS]
OPTIONS说明(常用),什么都不加默认列表当前正在运行的docker容器:
- -a :列出当前所有正在运行的容器+历史上运行过的
- -l :显示最近创建的容器。
- -n:显示最近n个创建的容器。
- -q :静默模式,只显示容器编号。
- –no-trunc :不截断输出。
退出容器
- exit 容器停止退出
- 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 run -d 容器名
#使用镜像centos:latest以后台模式启动一个容器docker run -d centos
问题:然后docker ps -a 进行查看, 会发现容器已经退出很重要的要说明的一点: Docker容器后台运行,就必须有一个前台进程.容器运行的命令如果不是那些一直挂起的命令(比如运行top,tail),就是会自动退出的。
这个是docker的机制问题,比如你的web容器,我们以nginx为例,正常情况下,我们配置启动服务只需要启动响应的service即可。例如service nginx start但是,这样做,nginx为后台进程模式运行,就导致docker前台没有运行的应用,这样的容器后台启动后,会立即自杀因为他觉得他没事可做了.所以,最佳的解决方案是,将你要运行的程序以前台进程的形式运行
查看容器日志
docker logs -f -t --tail 容器ID
- -f 加入最新的日志打印
- -t 加入打印的时间戳
- –tail number 显示最后多少条
查看容器内运行的进程
docker top 容器ID
查看容器内部细节
docker inspect 容器ID
进入正在运行的容器并以命令行交互
docker exec -it 容器ID bashShell
docker attach 容器ID
上述两个区别
- attach 直接进入容器启动命令的终端,不会启动新的进程
- exec 是在容器中打开新的终端,并且可以启动新的进程
从容器内拷贝文件到主机上
docker cp 容器ID:容器内路径 目的主机路径
总结:常用的命令
- attach Attach to a running container # 当前 shell 下 attach 连接指定运行镜像
- build Build an image from a Dockerfile # 通过 Dockerfile 定制镜像
- commit Create a new image from a container changes # 提交当前容器为新的镜像
- cp Copy files/folders from the containers filesystem to the host path #从容器中拷贝指定文件或者目录到宿主机中create
- Create a new container # 创建一个新的容器,同 run,但不启动容器
- diff Inspect changes on a container’s filesystem # 查看 docker 容器变化
- events Get real time events from the server # 从 docker 服务获取容器实时事件
- exec Run a command in an existing container # 在已存在的容器上运行命令
- export Stream the contents of a container as a tar archive # 导出容器的内容流作为一个 tar 归档文件[对应 import ]
- history Show the history of an image # 展示一个镜像形成历史images
- List images # 列出系统当前镜像
- import Create a new filesystem image from the contents of a tarball # 从tar包中的内容创建一个新的文件系统映像[对应export]
- info Display system-wide information # 显示系统相关信息
- inspect Return low-level information on a container # 查看容器详细信息
- kill Kill a running container # kill 指定 docker 容器
- load Load an image from a tar archive # 从一个 tar 包中加载一个镜像[对应 save]
- login Register or Login to the docker registry server # 注册或者登陆一个 docker 源服务器
- logout Log out from a Docker registry server # 从当前 Docker registry 退出
- logs Fetch the logs of a container # 输出当前容器日志信息
- port Lookup the public-facing port which is NAT-ed to PRIVATE_PORT # 查看映射端口对应的容器内部源端口
- pause Pause all processes within a container # 暂停容器
- ps List containers # 列出容器列表
- pull Pull an image or a repository from the docker registry server # 从docker镜像源服务器拉取指定镜像或者库镜像
- push Push an image or a repository to the docker registry server # 推送指定镜像或者库镜像至docker源服务器
- restart Restart a running container # 重启运行的容器
- rm Remove one or more containers # 移除一个或者多个容器
- rmi Remove one or more images # 移除一个或多个镜像[无容器使用该镜像才可删除,否则需删除相关容器才可继续或 -f 强制删除]
- run Run a command in a new container # 创建一个新的容器并运行一个命令
- save Save an image to a tar archive # 保存一个镜像为一个 tar 包[对应 load]
- search Search for an image on the Docker Hub # 在 docker hub 中搜索镜像
- start Start a stopped containers # 启动容器
- stop Stop a running containers # 停止容器
- tag Tag an image into a repository # 给源中镜像打标签
- top Lookup the running processes of a container # 查看容器中运行的进程信息
- unpause Unpause a paused container # 取消暂停容器
- version Show the docker version information # 查看 docker 版本号
- wait Block until a container stops, then print its exit code # 截取容器停止时的退出状态值
docker镜像
docker镜像是什么?
UnionFS(联合文件系统)
一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。 特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录
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等等。
平时我们安装进虚拟机的CentOS都是好几个G,为什么docker这里才200M??
对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供 rootfs 就行了。
由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别, 因此不同的发行版可以公用bootfs。
为什么 Docker 镜像要采用这种分层结构呢
最大的一个好处就是 - 共享资源 比如:有多个镜像都从相同的 base 镜像构建而来,那么宿主机只需在磁盘上保存一份base镜像,同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。
特点
Docker镜像都是只读的。当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。
Docker镜像commit操作补充
docker commit 提交容器副本使之成为一个新的镜像
docker commit -m=“提交的描述信息” -a=“作者” 容器ID 要创建的目标镜像名:[标签名]
案例演示
下载tomcat镜像到本地
docker run -it -p 8080:8080 tomcat
- -p 主机端口:docker容器端口
- -P 随机分配端口
- i:交互
- t:终端
故意删除上一步镜像生产tomcat容器的文档
以它为模板commit一个没有doc的tomcat新镜像atguigu/tomcat02
启动我们的新镜像并和原来的对比
docker容器数据卷
是什么
一句话:有点类似我们Redis里面的rdb和aof文件
能干嘛
- 容器的持久化
- 容器间继承+共享数据
数据卷(容器内添加)
直接命令添加
docker run -it -v /宿主机绝对路径目录:/容器内目录 镜像名
检查是否添加成功
docker inspect 容器ID
容器和宿主机之间数据共享
容器停止退出后,主机修改后数据是否同步
命令(带权限添加)
docker run -it -v /宿主机绝对路径目录:/容器内目录:ro 镜像名
ro: read only
DockerFile添加
根目录下新建mydocker文件夹并进入
在Dockerfile中使用VOLUME指令来给镜像添加一个或多个数据卷
# volume test
FROM centosVOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"]
CMD echo "finished,--------success1"
CMD /bin/bash
build后生成镜像
run容器
inspect查看主机对应默认地址
备注
Docker挂载主机目录Docker访问出现cannot open directory .: Permission denied解决办法:在挂载目录后多加一个–privileged=true参数即可
数据卷容器
是什么
命名的容器挂载数据卷,其它容器通过挂载这个(父容器)实现数据共享,挂载数据卷的容器,称之为数据卷容器
容器间传递共享(–volumes-from)
dockerFile
是什么
dockerFile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。
构建步骤
- 编写Dockerfile文件
- docker build
- docker run
dockerFile构建过程解析
docker File内容基础知识
- 每条保留字指令都必须为大写字母且后面要跟随至少一个参数
- 指令按照从上到下,顺序执行
- #表示注释
- 每条指令都会创建一个新的镜像层,并对镜像进行提交
Docker执行dockerfile的大致流程
- docker从基础镜像运行一个容器
- 执行一条指令并对容器作出修改
- 执行类似docker commit的操作提交一个新的镜像层
- docker再基于刚提交的镜像运行一个新容器
- 执行dockerfile中的下一条指令直到所有指令都执行完成
总结
从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段,
- Dockerfile是软件的原材料Docker镜像是软件的交付品
- Docker容器则可以认为是软件的运行态。
- Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。
1 Dockerfile,需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;
2 Docker镜像,在用Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像,当运行 Docker镜像时,会真正开始提供服务;
3 Docker容器,容器是直接提供服务的。
DockerFile体系结构(保留字指令)
- FROM 基础镜像,当前新镜像是基于哪个镜像的
- MAINTAINER 镜像维护者的姓名和邮箱地址
- RUN 容器构建时需要运行的命令
- EXPOSE 当前容器对外暴露出的端口
- WORKDIR 指定在创建容器后,终端默认登陆的进来工作目录,一个落脚点
- ENV 用来在构建镜像过程中设置环境变量
- ADD 将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包
- COPY 类似ADD,拷贝文件和目录到镜像中,将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置
- VOLUME 容器数据卷,用于数据保存和持久化工作
- CMD 指定一个容器启动时要运行的命令,Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换
- ENTRYPOINT ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数
- ONBUILD 当构建一个被继承的Dockerfile时运行命令,父镜像在被子继承后父镜像的onbuild被触发
案例
Base镜像(scratch)
Docker Hub 中 99% 的镜像都是通过在 base 镜像中安装和配置需要的软件构建出来的
CMD/ENTRYPOINT 镜像案例
CMD
Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换
ENTRYPOINT
docker run 之后的参数会被当做参数传递给 ENTRYPOINT,之后形成新的命令组合
自定义Tomcat9
-
mkdir -p /zzyyuse/mydockerfile/tomcat9
-
在上述目录下touch c.txt
-
将jdk和tomcat安装的压缩包拷贝进上一步目录
-
在/zzyyuse/mydockerfile/tomcat9目录下新建Dockerfile文件
-
构建
-
运行
docker run -d -p 9080:8080 --name myt9
-v /zzyyuse/mydockerfile/tomcat9/test:/usr/local/apache-tomcat-9.0.8/webapps/test
-v /zzyyuse/mydockerfile/tomcat9/tomcat9logs/:/usr/local/apache-tomcat-9.0.8/logs --privileged=true zzyytomcat9
-
验证
Docker常用安装
总体步骤
- 搜索镜像
- 拉取镜像
- 查看镜像
- 启动镜像
- 停止镜像
- 移除镜像
安装mysql
-
docker hub上面查找mysql镜像
-
从docker hub上(阿里云加速器)拉取mysql镜像到本地标签为5.6
-
使用mysql5.6镜像创建容器(也叫运行镜像)
docker run -p 12345:3306 --name mysql -v /zzyyuse/mysql/conf:/etc/mysql/conf.d -v /zzyyuse/mysql/logs:/logs -v /zzyyuse/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.6
命令说明:
-p 12345:3306:将主机的12345端口映射到docker容器的3306端口。
–name mysql:运行服务名字
-v /zzyyuse/mysql/conf:/etc/mysql/conf.d :将主机/zzyyuse/mysql录下的conf/my.cnf 挂载到容器的 /etc/mysql/conf.d
-v /zzyyuse/mysql/logs:/logs:将主机/zzyyuse/mysql目录下的 logs 目录挂载到容器的 /logs。
-v /zzyyuse/mysql/data:/var/lib/mysql :将主机/zzyyuse/mysql目录下的data目录挂载到容器的 /var/lib/mysql
-e MYSQL_ROOT_PASSWORD=123456:初始化 root 用户的密码。
-d mysql:5.6 : 后台程序运行mysql5.6
docker exec -it MySQL运行成功后的容器ID /bin/bash
安装redis
- 从docker hub上(阿里云加速器)拉取redis镜像到本地标签为3.2
- 使用redis3.2镜像创建容器(也叫运行镜像)
docker run -p 6379:6379 -v /zzyyuse/myredis/data:/data
-v /zzyyuse/myredis/conf/redis.conf:/usr/local/etc/redis/redis.conf
-d redis:3.2 redis-server /usr/local/etc/redis/redis.conf --appendonly yes
本地镜像发布到阿里云
镜像的生成方法:前面的DockerFile
阿里云开发者平台 :https://dev.aliyun.com/search.html
创建一个新的镜像:
docker commit [OPTIONS] 容器ID [REPOSITORY[:TAG]]
创建仓库镜像
- 命名空间
- 仓库名称
将镜像推送到registry
docker login --username= registry.cn-beijing.aliyuncs.com
docker tag [ImageId] registry.cn-beijing.aliyuncs.com/leyton/mycentos:[镜像版本号]
docker push registry.cn-beijing.aliyuncs.com/leyton/mycentos:[镜像版本号]
命令含义:
第一条登录
第二条提交到阿里云的仓库,并起一个名字与版本号
第三条:push到阿里云的仓库中,名字和版本号与第二条一致