Docker基础
# Docker
# Docker介绍
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。
# Docker组成
一个完整的 Docker 有以下几个部分组成:
DockerClient 客户端
Docker Daemon 守护进程
Docker Image 镜像
DockerContainer 容器
# Docker 的安装
在线安装和离线安装 Docker 阿里镜像加速仓库在线安装
# 安装步骤
1.官网中文安装参考手册 https://docs.docker-cn.com/engine/installation/linux/docker-ce/centos/
确定你是 CentOS7 及以上版本
$ cat /etc/redhat-release
yum 安装 gcc 相关
$ yum -y install gcc
$ yum -y install gcc -c++
卸载旧版本
2.安装需要的软件包
$ yum install -y yum-utils device-mapper-persistent-data lvm2
3.拉取docker镜像仓库
$ yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
4.更新 yum 软件包索引
$ yum makecache fast
5.安装 DOCKER CE
$ yum -y install docker-ce
启动 docker
$ systemctl start docker && systemctl enable docker
测试
$ docker version
$ docker run hello-world
6.配置镜像加速 阿里云镜像加速地址: https://ably8t50.mirror.aliyuncs.com
$ vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://ably8t50.mirror.aliyuncs.com"]
}
加载配置重启服务
$ systemctl daemon-reload
$ systemctl restart docker
卸载
$ systemctl stop docker
$ yum -y remove docker-ce
$ rm -rf /var/lib/docker
# Docker 私有仓库离线安装
Docker 私有仓库
docker-registry (opens new window)是官方提供的工具,可以用于构建私有的镜像仓库。本文内 容基于 docker-registry (opens new window)v2.x 版本。
# 配置仓库
配置私有仓库的时候,json 文件如下格式:
$ cat >> /etc/docker/daemon.json << EOF
{
"insecure-registries": ["192.168.100.10:5000"]
}
EOF
# 安装运行 docker-registry
使用官方 registry 镜像来运行:
$ docker run -d -p 5000:5000 --restart=always --name registry registry
默认情况下,仓库会被创建在容器的 /var/lib/registry 目录下。你可以通过 -v 参数来将镜像 文件存放在本地的指定路径。例如下面的例子将上传的镜像放到本地的 /opt/data/registry 目 录。
$ docker run -d \
-p 5000:5000 \
--name registry \
--restart=always \
-v /opt/data/registry:/var/lib/registry \
registry:latest
# 仓库使用
在私有仓库上传、搜索、下载镜像
创建好私有仓库之后,就可以使用 docker tag 来标记一个镜像,然后推送它到仓库。例如私有仓库地址为 127.0.0.1:5000。
先在本机查看已有的镜像。
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ubuntu latest ba5877dc9bec 6 weeks ago 192.7 MB
使用 docker tag 将 ubuntu:latest 这个镜像标记为 127.0.0.1:5000/ubuntu:latest。
格式为docker tag IMAGE[:TAG] [REGISTRY_HOST[:REGISTRY_PORT]/]REPOSITORY[:TAG]。
$ docker tag ubuntu:latest 127.0.0.1:5000/ubuntu:latest
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ubuntu latest ba5877dc9bec 6 weeks ago 192.7 MB
127.0.0.1:5000/ubuntu:latest latest ba5877dc9bec 6 weeks ago 192.7 MB
使用 docker push 上传标记的镜像。
$ docker push 127.0.0.1:5000/ubuntu:latest
The push refers to repository [127.0.0.1:5000/ubuntu]
373a30c24545: Pushed
a9148f5200b0: Pushed
cdd3de0940ab: Pushed
fc56279bbb33: Pushed
b38367233d37: Pushed
2aebd096e0e2: Pushed
latest: digest: sha256:fe4277621f10b5026266932ddf760f5a756d2facd505a94d2da12f4f52f71f5a size: 1568
用 curl 查看仓库中的镜像。
$ curl 127.0.0.1:5000/v2/_catalog
{"repositories":["ubuntu"]}
# 下载镜像
这里可以看到 {"repositories":["ubuntu"]},表明镜像已经被成功上传了。 先删除已有镜像,再尝试从私有仓库中下载这个镜像。
$ docker image rm 127.0.0.1:5000/ubuntu:latest
$ docker pull 127.0.0.1:5000/ubuntu:latest
Pulling repository 127.0.0.1:5000/ubuntu:latest
ba5877dc9bec: Download complete
511136ea3c5a: Download complete
9bad880da3d2: Download complete
25f11f5fb0cb: Download complete
ebc34468f71d: Download complete
2318d26665ef: Download complete
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
127.0.0.1:5000/ubuntu:latest latest ba5877dc9bec 6 weeks ago 192.7 MB
# Docker 的常用命令
docker info
信息描述docker version
版本信息docker --help
帮助命令
# 镜像命令
docker images 列出本地主机上的镜像
docker search 某个 xx 镜像的名字
$ docker search nginx
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
nginx Official build of Nginx. 15928 [OK]
jwilder/nginx-proxy Automated Nginx reverse proxy for docker con… 2101 [OK]
richarvey/nginx-php-fpm Container running Nginx + PHP-FPM capable of… 820 [OK]
jc21/nginx-proxy-manager Docker container for managing Nginx proxy ho… 288
linuxserver/nginx An Nginx container, brought to you by LinuxS… 160
# 下载镜像
$ docker pull 镜像名字[:TAG]
$ docker pull nginx 等价于 docker pull nginx:latest (latest 最新版)
删除某个 xx 镜像的名字 ID
删除镜像 docker rmi 镜像 ID (要先删除容器才能删)
删除单个 docker rmi -f 镜像 ID (-f 强制删除)
删除多个 docker rmi -f 镜像名 1:TAG 镜像名 2:TAG
删除全部 docker rmi -f $(docker images -qa)
# 导出镜像
[root@docker01 ~]# docker image list
REPOSITORY TAG IMAGE ID CREATED SIZE
centos latest ff426288ea90 3 weeks ago 207MB
nginx latest 3f8a4339aadd 5 weeks ago 108MB
'导出'
[root@docker01 ~]# docker image save centos > docker-centos.tar.gz
'导入镜像'
[root@docker01 ~]# docker image load -i docker-centos.tar.gz
e15afa4858b6: Loading layer 215.8MB/215.8MB
Loaded image: centos:latest
[root@docker01 ~]# docker image list
REPOSITORY TAG IMAGE ID CREATED SIZE
centos latest ff426288ea90 3 weeks ago 207MB
nginx latest 3f8a4339aadd 5 weeks ago 108MB
# 容器命令
启动容器
docker run [OPTIONS] IMAGE [COMMAND][ARG...]
(opens new window)
启动交互式容器
列出当前所有正在运行的容器
ps 列出当前所有正在运行的容器
# 退出容器
两种退出方式
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
-t 是加入时间戳
-f 跟随最新的日志打印
--tail 数字 显示最后多少条
查看容器内运行的进程
$ docker top 容器 ID
查看容器内部细节
$ docker inspect 容器 ID
进入正在运行的容器并以命令行交互
$ docker exec -it 容器 ID bashshell
重新进入 docker attach 容器 ID
上述两个区别
attach 直接进入容器启动命令的终端,不会启动新的进程
exec 是在容器中打开新的终端,并且可以启动新的进程
# Docker 容器数据卷
# 1.是什么
先来看看 Docker 的理念: 将运用与运行的环境打包形成容器运行,运行可以伴随着容器,但是我们 对数 据的要求希望是持久化的 容器之间希望有可能共享数据Docker 容器产生的数据,如果不通过 docker commit 生成新的镜像,使得数据做 为镜像的一部分保存下来, 那么当容器删除后,数据自然也就没有了。
为了能保存数据在 docker 中我们使用卷。
# 2.能干嘛
- 卷就是目录或文件,存在于一个或多个容器中,由 docker 挂载到容器,但不属 于联合文件系统,因此能够绕过 Union File System 提供一些用于持续存储或共
享数据的特性
: - 卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此 Docker 不 会在容器删除时删除其挂载的数据卷
# 特点:
1:数据卷可在容器之间共享或重用数据
2:卷中的更改可以直接生效
3:数据卷中的更改不会包含在镜像的更新中
4:数据卷的生命周期一直持续到没有容器使用它为止 容器的持久化 容器间继承+共享数据
# 数据卷
容器内添加数据卷 直接命令添加
$ docker run -it -v /宿主机绝对路径目录:/容器内目录 镜像名
查看数据卷是否挂载成功
$ docker inspect 容器 ID
容器和宿主机之间的数据共享 主机创建文件,容器可以同步 容器停止退出后,主机修改后数据是否同步 同步
# 命令(容器只读权限)
$ docker run -it -v /宿主机绝对路径目录:/容器内目录:ro 镜像名
实例:
$ docker run -d -p 80:80 -v /opt/data:/usr/share/nginx/html --name nginx nginx:latest
$ docker run -d -p 80:80 -v /opt/data:/usr/share/nginx/html:rw --name nginx nginx:latest
# Dockerfile 添加
根目录下新建 mydocker 文件夹并进入 ,可在 Dockerfile 中使用 VOLUME 指令来给镜像添加一个或多个数据卷
VOLUME ['/dataVolumeContainer',"/dataVolumeContainer2","/dataVolumeCont ainer3"]
说明:
- 出于可移植和分享的考虑,用-v 主机目录:容器目录这种方法不能够直接在 Dockerfile 中实现。
- 由于宿主机目录是依赖于特定宿主机的,并不能够保证在所有的宿主机上都存在 这样的特定目录。
Dockerfile 构建
FROM centos
VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"]
CMD echo "finished-----success1"
CMD /bin/bash
构建镜像
$ docker build -f /mydocker/dockerfile2 -t zzyy/centos .
# run 容器
$ docker run -it zzyy/centos
通过上述步骤,容器内的卷目录地址已经知道,对应的主机目录地址哪??
$ docker inspect 容器 ID 可以查看主机对应默认地址口
备注
- Docker 挂载主机目录 Docker 访问出现 cannot open directory .: Permission deniedy
- 解决办法:在挂载目录后多加一个--privileged=true 参数即可
# Docker 镜像
是什么? 镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环 境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、 环境变量和配置文件。
UnionFS (联合文件系统)
- UnionFS (联合文件系统) :
Union 文件 系统(UnionFS) 是一种分层、轻量级并 且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加, 同时可以将不同目录挂载到同一个虚拟文件
系统下(unite several directories into a single virtual filesystem)。Union 文件系统是 Docker 镜像的基础。 镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体 的应用镜像。 - 特性:
一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统, 联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文 件和目录
# Docker 镜像加载原理
Docker 镜像加载原理:
docker 的镜像实际上由一层一层的文件 系统组成,这种层级的文件系统 UnionFS.botfs(boot fle system)
主要包含 bootloader 和 kernel, botoader 主要是引导 加载 kernel,Linux 刚启动时会加载 bootfs 文件系统,在 Docker 镜像的最底层 是 botfs。这一层与我们典型的 Linux/Unix 系统是一样的,包含 boot 加载器和 内核。当 boot 加载完成之后整个内核就都在内存中了,此时内存的使用权已由 bootfs 转交给内核,此时系统也会卸载 boofs.roots (root file system)
,在 botfs 之上。 包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件。rootfs就 是各种不同的操作系 统发行版,比如 Ubuntu, Centos 等等。为什么 Docker 镜像要采用这种分层结构呢最大的一个好处就是一共享资源
比如:有多个镜像都从相同的 base 镜像构建而来,那么宿主机只需在磁盘上保存 一份 base 镜像, 同时内存中也只需加载-份 base 镜像,就可以为所有容器服务了。而且镜像的每 一层都可以被共享。
# 特点
Docker 镜像都是只读的 当容器启动时,一个新的可写层被加载到镜像的项部。 这一层通常被称作"容器层","容器层"之下的都叫"镜像层”。
docker镜像 commit 操作补充
dockercommit 提交容器副本使之成为--个新的镜像 docker commit -m=“提交的描述信息”-a=”作者”容器 ID 要创建的目标镜像 名:[标签名]
# 案例演示
1. 从 Hub 上下载 tomcat 镜像到本地并成功运行
$ docker run -it -p 8080:8080 tomcat
-p 主机端口:docker 容器端口
-P 随机分配端口
-i 交互
-t 终端
2.故意删除上一步镜像生产 tomcat 容器的文档
$ docker exec -it 容器名 /bin/bash
$ cd webapps
$ rm -rf docs
3. 也即当前的 tomcat 运行实例是一- 个没有文档内容的容器,以它为模板 commit 一个没有 doc 的 tomcat 新镜像 atguigu/tomcat02
$ docker commit -a=“zzyy”-m="del tomcat docs" 容器 ID atguigu/tomcat02:1.2
4.启动我们的新镜像并和原来的对比
- 启动 atguigu/tomcat02,它没有 docs
- 新启动原来的 tomcat,它有 docs