石一歌的Docker基础笔记 [狂神]
Docker
- 文档
- 仓库
概述
Docker出现
- 开发和运维使用两套环境,环境配置十分麻烦(Windows开发,Linux上运行)。
Docker给以上问题提出了解决方案:
Java --- Jar(环境)---打包项目带上环境(镜像)---Docker仓库(应用商店)---下载镜像---直接运行 - Docker的核心思想:隔离。
即将应用打包装箱,每个箱子是互相隔离的,可以将服务器利用到极致。
虚拟机 | Docker |
---|---|
linux centos原生镜像(一个电脑) | 隔离镜像(最核心的环境 +jdk +mysql等) |
需要开启多个虚拟机 | 运行镜像就可以了 |
几GB | 几MB |
Docker历史
- 2010年,旧金山成立
dotCloud
,底层技术为LXC
(后被Libcontainer
代替)。 - 基于
Go
语言,开发内部工具Docker
。 - 2013年3月,
Solomon?Hykes
开源Docker
。 - 2014年6月9日,
Docker
1.0 版本正式发布。
对比虚拟机
Docker特点
- 不模拟完整的操作系统,系统内核(kernel)非常小,更少的抽象层(GuestOS:如Centos)
- 容器内的应用直接运行在宿主机的内核,容器本身没有自己的内核,也没有虚拟硬件。
- 每个容器相互隔离,内部都有属于自己的文件系统,互不影响。
Docker优点
- 更高效的利用系统资源
- 更快速的启动时间
- 一致的运行环境
- 持续交付和部署
- 更轻松的迁移
- 更轻松的维护和扩展
安装
Docker基本组成
- 镜像(image):镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件。它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。相当于一个模板,通过这个模板来创建容器服务,可以通过一个镜像创建多个容器。
- 容器(container):独立运行一个或一组应用/基本命令有:启动,停止,删除等/可理解为一个简单的linux系统。
- 仓库(repository):存放镜像的地方(公有/私有)
环境准备
内核3.10+,版本7.0+
[root@faetbwac ~]# uname -r
3.10.0-1160.53.1.el7.x86_64
[root@faetbwac ~]# cat /etc/os-release
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"
CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"
安装操作
# 卸载旧Docker
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
# 安装依赖
yum install -y yum-utils
# 设置阿里云镜像仓库
yum-config-manager \
--add-repo \
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 更新yum软件包索引
yum makecache fast
# 安装docker引擎
yum install docker-ce docker-ce-cli containerd.io
卸载操作
# 卸载docker引擎
yum remove docker-ce docker-ce-cli containerd.io
# 删除镜像、容器、数据卷和配置文件
rm -rf /var/lib/docker
rm -rf /var/lib/containerd
阿里云镜像加速
mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://k1boskqx.mirror.aliyuncs.com"]
}
EOF
systemctl daemon-reload
systemctl restart docker
底层原理
Docker是一个Client-Server结构的系统,以守护进程运行在主机上。通过Socket从客户端进行访问。主要组成如下:
- 服务器,是一种长期运行的程序,称为守护进程
- REST API,指定程序用来与守护进程对话并指示
命令
帮助命令
命令文档
# docker版本信息
docker version
# 系统级别的信息,包括镜像和容器的数量
docker info
# 命令帮助信息
docker xx --help
服务命令
# 启动docker服务
systemctl start docker
# 停止docker服务
systemctl stop docker
# 重启docker服务
systemctl restart docker
# 查看docker服务状态
systemctl status docker
# 设置开机启动docker服务
systenctl enable docker
镜像命令
# 查看本地镜像
docker images [OPTIONS] [REPOSITORY[:TAG]]
[options]:
-a :列出本地所有的镜像(含中间映像层,默认情况下,过滤掉中间映像层);
--digests :显示镜像的摘要信息;
-f :显示满足条件的镜像;
--format :指定返回值的模板文件;
--no-trunc :显示完整的镜像信息;
-q :只显示镜像ID。
# 搜索镜像
docker search [OPTIONS] TERM
[options]:
--automated :只列出 automated build类型的镜像;
--no-trunc :显示完整的镜像描述;
-f <过滤条件>:列出收藏数不小于指定值的镜像。
参数说明:
NAME: 镜像仓库源的名称
DESCRIPTION: 镜像的描述
OFFICIAL: 是否 docker 官方发布
stars: 星星数。
AUTOMATED: 自动构建。
# 拉取镜像
docker pull [OPTIONS] NAME[:TAG|@DIGEST]
[options]:
-a :拉取所有 tagged 镜像
--disable-content-trust :忽略镜像的校验,默认开启
实例:
[root@faetbwac ~]# docker pull nginx
Using default tag: latest # 默认latest
latest: Pulling from library/nginx
a2abf6c4d29d: Pull complete # 分层下载,联合文件系统,不同镜像的相同文件无需再次下载
a9edb18cadd1: Pull complete
589b7251471a: Pull complete
186b1aaa4aa6: Pull complete
b4df32aa5a72: Pull complete
a0bcbecc962e: Pull complete
Digest: sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31 # 签名
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest # 真实地址,可直接拉取
# 移除镜像
docker rmi [OPTIONS] IMAGE [IMAGE...]
[options]:
-f :强制删除;
--no-prune :不移除该镜像的过程镜像,默认移除;
docker rmi -f $(docker images -aq) #全部移除
# 镜像历史
docker history [OPTIONS] IMAGE
[options]:
-H :以可读的格式打印镜像大小和日期,默认为true;
--no-trunc :显示完整的提交记录;
-q :仅列出提交记录ID。
容器命令
# 创建并启动容器
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
[options]:
--name=容器名 :命名容器以区分不同容器
-d :在后台运行容器(类似centos的系统容器,必须要指定前台进程)
-it :使用交互方式运行,进入容器查看内容
-p :指定容器的端口
-p ip:主机端口:容器端口
-p 主机端口:容器端口(常用)
-p 容器端口
容器端口
-P :随机容器的端口
--rm :用完即删(测试)
--net somenetwork :网络配置
-e username="ritchie" :设置环境变量
-v 主机目录:容器目录 :挂载数据卷
--link 容器名 镜像名 :修改容器hosts文件加入目标容器
[command]:
/bin/bash :控制台
# 查看本地容器
docker ps [OPTIONS]
[options]:
-a :列出正在运行的容器包括历史容器
-n=? :显示最近创建的容器
-q :只显示当前容器的编号
# 启动容器
docker start [OPTIONS] CONTAINER [CONTAINER...]
# 重启容器
docker restart [OPTIONS] CONTAINER [CONTAINER...]
# 关闭容器
docker stop [OPTIONS] CONTAINER [CONTAINER...]
# 强制关闭容器
docker kill [OPTIONS] CONTAINER [CONTAINER...]
# 删除容器
docker rm [OPTIONS] CONTAINER [CONTAINER...]
docker rm -f $(docker ps -aq) #全部移除
docker ps -a -q|xargs docker rm #全部移除
[options]:
-f :通过 SIGKILL 信号强制删除一个运行中的容器。
-l :移除容器间的网络连接,而非容器本身。
-v :删除与容器关联的卷。
# 查看容器日志
docker logs [OPTIONS] CONTAINER
[options]:
-f : 跟踪日志输出
--since :显示某个开始时间的所有日志
-t : 显示时间戳
--tail :仅列出最新N条容器日志
# 查看容器进程
docker top [OPTIONS] CONTAINER [ps OPTIONS]
# 查看容器元数据
docker inspect [OPTIONS] NAME|ID [NAME|ID...]
# 查看容器状态
docker stats [OPTIONS] [CONTAINER...]
# 进入容器
docker attach [OPTIONS] CONTAINER
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
[options]:
-d :分离模式: 在后台运行
-i :即使没有附加也保持STDIN 打开
-t :分配一个伪终端
# 退出容器
Exit(CTRL+d/CTRL+c) :容器停止退出
CTRL+p+q :容器不停止退出
# 拷贝文件
docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-
docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH
[options]:
-L :保持源目标中的链接
可视化
Portainer
查找到商业版需要许可证,尽管有5个免费的,还是选择社区版。
官方提示portainer/portainer存储库已弃用。这里我直接最新版,经测试2.9的汉化依旧可以使用。
[Portainer官网](安装 Portainer CE - Portainer 文档)
汉化帖子
# 部署Portainer
docker volume create portainer_data
docker run -d -p 8000:8000 -p 9443:9443 --name portainer \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
-v /root/public:/public \
portainer/portainer-ce:2.11.1
[options]:
-d:容器在后台运行;
-p 8000:8000 :端口映射
–restart 标志会检查容器的退出代码,并据此来决定是否要重启容器,默认是不会重启。
–restart=always:自动重启该容器
-v /var/run/docker.sock:/var/run/docker.sock :把宿主机的Docker守护进程(Docker daemon)默认监听的Unix域套接字挂载到容器中
-v portainer_data:/data :把宿主机portainer_data数据卷挂载到容器/data目录
–name prtainer-test : 给容器起名为portainer
# 汉化Portainer
下载汉化文件,解压出public文件夹传输至系统root目录下
Rancher(CI/CD)
镜像详解
UnionFS(联合文件系统)
- 联合文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。联合文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
- 特性:一次同时加载多个文件系统,但从外面看起来只能看到一个文件系统。联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
镜像加载原理
Docker的镜像实际由一层一层的文件系统组成:
- bootfs(boot file system)主要包含bootloader和kernel。bootloader主要是引导加载kernel,完成后整个内核就都在内存中了。此时内存的使用权已由bootfs转交给内核,系统卸载bootfs。可以被不同的Linux发行版公用。
- rootfs(root file system),包含典型Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。rootfs就是各种不同操作系统发行版(Ubuntu,Centos等)。因为底层直接用Host的kernel,rootfs只包含最基本的命令,工具和程序就可以了。
分层理解
- 所有的Docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的容器层。
- 容器在启动时会在镜像最外层上建立一层可读写的容器层(R/W),而镜像层是只读的(R/O)。
提交容器
# 提交容器为新的镜像
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
[options]:
-a :提交的镜像作者
-c :使用Dockerfile指令来创建镜像
-m :提交时的说明文字
-p :在commit时,将容器暂停
数据卷
为了实现数据持久化,使容器之间可以共享数据。可以将容器内的目录,挂载到宿主机上或其他容器内,实现同步和共享的操作。即使将容器删除,挂载到本地的数据卷也不会丢失。
数据卷命令
# 数据卷命令
docker volume COMMAND
Commands:
create 创建卷
inspect 展示卷信息
ls 列出所有卷
prune 移除所有不使用的卷
rm 移除卷
挂载数据卷
# 冷挂载(容器启动时挂载/dockerfile挂载)
Bind(指定路径挂载)
-v /主机路径:容器内路径
Volume(Docker路径挂载)
-v 容器内路径 :匿名挂载
-v 卷名:容器内路径 :具名挂载
tmpfs(内存挂载)
--tmpfs 容器内路径
# 热挂载
参照文末链接,很少这么做
docker rm -v 命令不会删除具名挂载和指定路径挂载的卷,而匿名挂载会被删除
-v 容器内路径:ro/rw 可改变读写权限
- ro readonly #只读
- rw readwrite #可读可写
Bind | Volume | tmpfs | |
---|---|---|---|
volume 位置 | 可指定任意位置 | /var/lib/docker/volumes/... | 宿主机内存中 |
对已有mount point 影响 | 隐藏并替换为 volume | 原有数据复制到 volume | - |
是否支持单个文件 | 支持 | 不支持,只能是目录 | - |
权限控制 | 可设置为只读,默认为读写权限 | 可设置为只读,默认为读写权限 | - |
移植性 | 移植性弱,与 host path 绑定 | 移植性强,无需指定 host 目录 | - |
是否支持持久化 | 支持 | 支持 | 不支持 |
挂载复制
这里狂神的用的名字是容器数据卷,查看容器的元数据可知,多个容器挂载到宿主的同一位置,称为挂载复制更恰当。不论父容器挂载方式如何,都可以使用。
# 挂载复制
--volumes-from 容器名称
Dockerfile挂载
在创建镜像的过程中可以指定挂载卷(匿名挂载)。
FROM centos
VOLUME ["/volume1"]
CMD echo "----end----"
CMD /bin/bash
Dockerfile
用来构建Docker镜像的文件。
Dockerfile构建镜像步骤
- 编写Dockerfile文件
- 执行
docker build
命令
Dockerfile文件
-
构建过程
-
每个保留关键字(指令)忽略大小写,建议大写
-
从上到下顺序执行
-
"#" 表示注释
-
每一个指令都会创建提交一个新的镜像层并提交
-
-
Dockerfile指令
命令 效果 FROM 基础镜像:Centos/Ubuntu MAINTAINER 镜像作者+邮箱 RUN 镜像构建的时运行命令 ADD 为镜像添加内容(压缩包) WORKDIR 镜像工作目录(进入容器时的目录) VOLUME 挂载的目录 EXPOSE 暴露端口配置 CMD/ENTRYPOINT 容器启动时运行命令 COPY 类似于ADD,将文件拷贝到镜像中 ENV 构建时设置环境变量 ONBUILD 为镜像添加触发器。其参数是任意一个Dockerfile 指令。构建子镜像时执行。
构建镜像
构建文件名为Dockerfile的,可以省略末尾的
.
# Dockerfile构建镜像
docker build [OPTIONS] PATH | URL | -
[options]:
--build-arg=[] :设置镜像创建时的变量;
--cpu-shares :设置 cpu 使用权重;
--cpu-period :限制 CPU CFS周期;
--cpu-quota :限制 CPU CFS配额;
--cpuset-cpus :指定使用的CPU id;
--cpuset-mems :指定使用的内存 id;
--disable-content-trust :忽略校验,默认开启;
-f :指定要使用的Dockerfile路径;
--force-rm :设置镜像过程中删除中间容器;
--isolation :使用容器隔离技术;
--label=[] :设置镜像使用的元数据;
-m :设置内存最大值;
--memory-swap :设置Swap的最大值为内存+swap,"-1"表示不限swap;
--no-cache :创建镜像的过程不使用缓存;
--pull :尝试去更新镜像的新版本;
--quiet, -q :安静模式,成功后只输出镜像 ID;
--rm :设置镜像成功后删除中间容器;
--shm-size :设置/dev/shm的大小,默认值是64M;
--ulimit :Ulimit配置。
--squash :将 Dockerfile 中所有的操作压缩为一层。
--tag, -t :镜像的名字及标签,通常 name:tag 或者 name 格式;可以在一次构建中为一个镜像设置多个标签。
--network :默认 default。在构建期间设置RUN指令的网络模式
CMD
&ENTRYPOINT
-
exec
模式和shell
模式exec
模式- 容器中的1号进程是任务进程
- 不会直接通过
shell
执行命令,无法直接获取环境变量,可以执行shell
命令获取环境变量
shell
模式- 容器中的1号进程不是任务进程,而是
bash
进程 - 会直接通过
shell
执行命令,可以直接获取环境变量
- 容器中的1号进程不是任务进程,而是
-
CMD
指令和ENTRYPOINT
指令-
CMD
指令docker run 时可以用命令行参数覆盖
CMD
指令(全模式)dockerfile中的多个
CMD
命令,会被覆盖,只保留最后一条-
为
ENTRYPOINT
提供默认参数CMD ["param1","param2"]
-
exec
模式CMD ["executable","param1","param2"]
-
shell
模式CMD command param1 param2
-
-
ENTRYPOINT
指令docker run 时可以用命令行参数追加到
ENTRYPOINT
指定命令的参数列表中(exec
模式)dockerfile中的多个
ENTRYPOINT
命令,会被覆盖,只保留最后一条-
exec
模式命令行上指定的参数会作为参数添加到 ENTRYPOINT 指定命令的参数列表中
ENTRYPOINT ["executable", "param1", "param2"]
-
shell
模式完全忽略命令行参数
ENTRYPOINT command param1 param2
-
-
同时使用
- 如果 ENTRYPOINT 使用了 shell 模式,CMD 指令会被忽略
- 如果 ENTRYPOINT 使用了 exec 模式,CMD 指定的内容被追加为 ENTRYPOINT 指定命令的参数
- 如果 ENTRYPOINT 使用了 exec 模式,CMD 也应该使用 exec 模式
-
发布镜像
# 登录镜像仓库
docker login [OPTIONS] [SERVER]
[options]:
-u :登陆的用户名
-p :登陆的密码
# 推送镜像
docker push [OPTIONS] NAME[:TAG]
[options]:
--disable-content-trust :忽略镜像的校验,默认开启
网络
dockerm默认提供的网络模式
- bridge:多由于独立container之间的通信
- host: 直接使用宿主机的网络,端口也使用宿主机的
- overlay:当有多个docker主机时,跨主机的container通信
- macvlan:每个container都有一个虚拟的MAC地址
- none: 禁用网络
网络命令
# 网络命令
docker network COMMAND
Commands:
connect 将某个容器连接到一个docker网络
create 创建一个docker局域网络
disconnect 将某个容器退出某个局域网络
inspect 显示某个局域网络信息
ls 显示所有docker局域网络
prune 删除所有未引用的docker局域网络
rm 删除docker网络
docker0
-
云服务器网络
查看网络
ip addr
-
环回地址
# lo inet 127.0.0.1/8
-
内网地址
# eth0 172.19.132.127/20
-
Docker网络地址
# docker0: 172.17.0.1/16
-
-
docker0
docker网桥,Docker中的所有容器通过虚拟网卡连接到docker0进行网络访问,容器之间也可以通过docker0访问,
原理:新建容器时创建在虚拟接网卡(veth-pair),一端在默认的docker0或指定网桥上,一端在放到新容器中修改名字作为eth0, 从网桥可用地址段中获取一个空闲地址分配给容器的 eth0,并配置默认路由到桥接网卡
下面介绍几种查看容器网络的方法
-
ip addr
直接进入容器执行
ip addr
命令即可。需要注意的是最新版tomcat镜像没有
ip addr
命令,需要先进行apt update && apt install -y iproute2
命令安装相关工具 -
docker inspect
查看容器的元数据,NetworkSettings字段中Networks有详细的数据
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'
可以直接提取容器的ip数据 -
docker network inspect
查看网络元数据,Containers字段也详细介绍ip数据
-
容器互联
容器没有
ping
命令,可以执行apt-get update && apt install iputils-ping
安装
--link
可以通过
docker run --link CONTAINER IMAGE
,在启动的容器内的hosts文件写入目标容器的地址,从而直接通信
-
自定义网络
加入同一自定义网络的不同容器间可通过ip地址或容器名/id连通
# 创建自定义网络 docker network create [OPTIONS] NETWORK [options]: -d :网络类型 --subnet :子网地址 --gateway :网关地址 # 启动容器指定网络 docker run -itd --network NETWORK IMAGE
-
容器连通网络
可以将原有容器添加目标容器的网段,相当于原有容器在目标容器添加一个虚拟ip,实现跨网段的容器互联
# 容器连通网络 docker network connect [OPTIONS] NETWORK CONTAINER
参考链接
- 狂神说docker(最全笔记)
- 为什么docker不适合mysql_为什么不建议把数据库部署在Docker容器内
- 给一个正在运行的Docker容器动态添加Volume
- Docker基础-19-网络-bridge模式和docker0详解
- docker network create