Docker 笔记汇总
一、名词说明
Dockerfile | 镜像构建文件 |
---|---|
Docker Images | 镜像;生成容器 |
Docker Containers | 容器;微型系统 |
Docker Volumes | 卷;存放容器运行数据 |
Docker Networks | docker 自有网络管理 |
Docker Context | |
Docker Compose | 编排服务;多个或一组相关联的 docker 服务管理 |
Docker Machine | docker 管理工具客户端 |
Docker Swarm | docker 服务集群管理工具 |
作者:[Sol·wang] - 博客园,原文出处:https://www.cnblogs.com/Sol-wang/p/17063192.html
二、Linux 环境部署
红帽系 RHEL 7+ 下的 Linux 环境部署。
2.1 卸载原有安装包
dnf remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine \
podman \
runc
2.2 系统新增 Docker Repo
dnf install -y yum-utils
# 系统追加 Docker 镜像源
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 变更为国内<南京大学>镜像源
# 参考:https://mirror.nju.edu.cn/mirrorz-help/docker-ce/?mirror=NJU#fedoracentosrhel
sed -i 's+download.docker.com+mirror.nju.edu.cn/docker-ce+' /etc/yum.repos.d/docker-ce.repo
2.3 安装 Docker
# 安装引擎
dnf install docker-ce docker-ce-cli containerd.io docker-compose-plugin
# 要安装特定版本的 Docker 引擎,在存储库中列出可用版本,选择并安装:
# 列出存储库中可用的版本并对其进行排序,按版本号排序
dnf list docker-ce --showduplicates | sort -r
# 安装特定版本
dnf install docker-ce-{version} docker-ce-cli-{version} containerd.io docker-compose-plugin
# 自定义docker网卡地址(避免于宿主机网段冲突,导致无法上网)
echo '{"bip":"172.17.0.1/16"}' > /etc/docker/daemon.json
# 启动 docker 服务
systemctl start docker
# 开机自启动
systemctl enable docker
systemctl enable containerd
2.4 配置国内Hub
参考<南京大学>镜像站:https://mirror.nju.edu.cn/
# 这里配置为<南京大学>镜像站
# 注意:已存在得 daemon.json 不可覆盖
echo '{"registry-mirrors": ["https://docker.nju.edu.cn/"]}' > /etc/docker/daemon.json
# 重启服务生效
systemctl restart docker
# 验证Hub变更效果(Registry Mirrors 的值,倒数第二行)
docker info
2.5 卸载 Docker
# 卸载 Docker-Engine、CLI、Containerd、Docker-Compose 软件包
dnf remove docker-ce docker-ce-cli containerd.io docker-compose-plugin
# 主机上的映像、容器、卷或自定义配置文件 不会自动删除;删除所有映像、容器、卷
rm -rf /var/lib/docker
rm -rf /var/lib/containerd
三、常用命令
3.1 Repository
# 登录/登出 Registry
docker login/logout
# 搜索仓库中的镜像
docker search [username/]{image}
# 镜像下载到本地
docker pull {image}[:{tag}]
# 镜像推送到仓库
docker push {username}/{image}[:{tag}]
# 本地镜像标记成指定仓库的镜像
docker tag {source_image}[:{tag}] [{hub_id}/][{username}/]{target_image}[:{tag}]
3.2 基础命令
# 查看docker系统信息
docker info
# 查看docker版本
docker version
# 显示已有对象的 列表/删除/详细
docker image/container/volume/network ls/rm/inspect {id|name}
# 删除对象
# -f,--force:强制删除正在运行的对象
# -l,--link:删除指定的连接
# -v,--volumes:删除关联的卷
docker rm container {name} [-flv]
# 对象的详情说明
docker inspect image/container/volume/network
# 清理无用的未启动的对象
# --force,-f:强制删除正在运行的对象
docker image/container/volume/network prune [--force]
# 清理无用的未运行的容器对象
# -f,--force:强制删除正在运行的容器
# -v,--volumes:包含关联的卷
docker container prune [-fv]
# docker 程序内部管理
# df:docker系统磁盘使用情况
# --verbose:-v,更详细的说明
docker system df [--verbose]
# docker 服务详细信息
docker system info
# 清理 未运行的、无用的、缓存等 对象
# --volumes:-v,包含关联的卷
docker system prune [--volumes]
3.3 Network
# 将指定容器连接到指定网络
docker network connect [--ip 10.10.36.101] {net-name} {container-name}
# 断开指定网路与指定容器的连接
docker network disconnect {net-name} {container-name}
# 创建自定义网络
# - dirver:-d,网络类型,默认 bridge
# bridge:桥连模式
# host:本地网络
# overlay:用于集群中容器的跨主机网络访问,只能在swarm的manager节点上创建
# - subnet:网段,子网
# - ip-range:从子范围分配容器IP
# - gateway:主子网的IPv4或IPv6网关
docker network create --driver=bridge --subnet=172.17.5.0/24 --gateway=172.17.5.254 {new-name}
# 删除多个网络
# - f:force 强制删除
# - v:volume 包含关联的卷
docker network rm {net1} {net2} [-fv]
3.4 Image
# 镜像 查询、下载、推送、运行容器
docker search/pull/push/run {image}
# 好像只能通过 image-id 删除镜像
docker rmi {image-id}:[tag]
# 创建镜像
# -t:tag;镜像名称及标签
# -f:file;指定Dockerfile文件所在路径及文件名称;默认值=./Dockerfile
# source-path:生成镜像的打包目录,默认值=.(当前目录);Dockerfile中的COPY以此目录为基准
docker build -t [{HubID}]/{image-name}:{tag} [-f {dockerfile-path}] [{source-path}]
# example a:docker build -t custom-name:1.0 -f /opt/dockerfile.debug .
# example b:docker build -t custom-name
#
# 拉取镜像
docker pull [{HubID}]/{image-name}:{tag}
# 推送镜像
docker push [{HubID}]/{image-name}:{tag}
# 打包镜像
docker save {镜像名} --output {path/filename}.tar
docker save {镜像名} > {path/filename}.tar
docker save {镜像名} | gzip > {path/filename}.tar.gz
# 解压镜像到存储库
docker load --input {path/filename}.tar
docker load < {path/filename}.tar
docker load < {path/filename}.tar.gz
# 查看全部镜像列表
docker images -a
# 查看过滤后的镜像列表(无效的)
docker images --filter dangling=true
# 删除镜像 remove images
docker rmi {hub_id}/{repo-name}:{tag}
3.5 Container
# 用镜像生成一个容器运行
# -d:容器系统可后台运行
# -i:保持终端会话不断开
# -t:与终端交互方式,输入输出模式
docker run -dit --name {新容器名称} \
-c 2 \ # 限制CPU个数
-m 4G \ # 限制内存大小(BKMG)
--privileged \ # 赋予高系统权限
-e LANG=C.utf8 \ # 系统环境变量-容器字符集
-e TZ=Asia/Shanghai \ # 系统环境变量-容器时区
--network {net-name} \ # 指定使用的网卡
--ip {ip-address} \ # 指定IP地址(前提是使用自定义网卡)
-p {cPort}:{port} \ # 宿主端口映射
--hostname {host-name} \ # 设主机名称
--restart unless-stopped \ # 自动重启
-v /etc/localtime:/etc/localtime # 卷宿主文件映射
{镜像名}:{tag}
#/ MySQL 示例:
# -c:cpu可核心数、-m 内存可使用的容量(BKMG)、--name:容器名称,--restart:自启动
# -p:端口绑定,-e:环境变量(默认字符集,初始密码,创建库),-v:与主机设定相同时区
docker run -d -c 4 -m 6G --name mysql.t.index --restart unless-stopped \
-p 3306:3306 \
-e LANG=C.utf8 \
-e TZ=Asia/Shanghai \
-e MYSQL_ROOT_PASSWORD=sa. \
-e MYSQL_DATABASE=testdb \
mysql:8.0.31
# 查看容器列表
# -a:全部
# --format:格式化显示
# --no-trunc:不省略显示,内容全显示
docker ps -a --format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Command}}" --no-trunc
# 运行容器内命令
# -i:interactive 相互保持打开交互输入流
# -t:tty 伪终端,模拟终端
# -e:配置环境变量
docker exec -t -e LANG=C.utf8 {容器名} {容器内系统命令}
# 容器其它操作项
# -commit:当前容器现状生成 new image
# -cp:拷贝; 容器到主机 {容器Id}:{Path} {LocalPath},主机到容器 {LocalPath} {容器Id}:{Path}
# -start|restart|rename|pause|unpause|stop|rm:启动,重启,重命名,暂停,恢复,停止,删除
# -inspect|stats|top|port|kill|logs:描述,时时资源使用情况,进程状况,用到的端口,杀死,日志
# -diff:容器内文件系统的变动历史,运行变化(A - Add, D - Delete, C - Change)
docker commit|cp|start|restart|rename|pause|unpause|stop|rm|stats|top|port|kill|logs|diff {容器}
# 删除容器
# -f,--force:强制
# -v,--volumes:带上关联的卷
docker rm {container} [-fv]
# 修改容器属性
docker update --restart {新值}
# 当前容器生成新镜像
docker commit {容器} {新镜像名称}
# 拷贝容器内文件 到主机目录
docker cp {容器}:{path} {local_path}
# 拷贝主机文件 到容器内目录
docker cp {local_path} {container}:{path}
# 容器内文件变更情况
docker diff {container}
# 时时日志 -f
docker logs --follow {container}
# 最新日志 -n
docker logs --tail={行数} {container}
# 指定日期时间之前
docker logs --until={时间} {container}
# 指定日期时间之后
docker logs --since={时间} {container}
# 硬件资源时时使用情况
# --no-stream:仅打印出当前一次
docker stats [--no-stream] {container}
docker run / exec 常用参数含义说明
-t |
伪终端,模拟终端效果,完成交互内容显示 |
-h |
设置容器的 hostname |
-d |
后台运行 |
-i |
保持以交互模式运行容器,通常与 -t 同时使用 |
-P |
随机端口映射,容器内部端口随机映射到主机的端口 |
-p |
指定端口映射,{主机端口}:{容器端口} |
--dns-search |
指定容器DNS搜索域名,默认和宿主一致 |
-e |
设置容器内的环境变量 |
--cpuset |
绑定容器到指定CPU运行 |
-m |
设置容器使用内存最大值 |
--net |
指定容器的网络连接类型 |
--link |
添加链接到另一个容器 |
--expose |
开放一个端口或一组端口 |
-v ,--volume |
绑定一个卷(数据文件)到宿主机 |
3.6 Dockerfile
指令 | 说明 |
---|---|
FROM | 依赖的上一级载体镜像 |
MAINTAINER | 维护者信息 |
ARG | 接收 Build 变量参数,覆盖默认值 |
RUN | 需要执行的命令;必要的环境准备(install/init) |
EXPOSE | 开放的端口 |
WORKDIR | 进入容器的根目录 |
USER | 容器内系统使用的账户 |
ENV | 定义环境变量 |
ADD | 加入需要的文件;复制到并解压 |
COPE | 加入需要的文件;仅复制 |
VOLUME | 卷;宿主机与容器之间的绑定文件夹路径 |
CMD | 容器启动后默认运行的命令行;会被外部参数覆盖 |
ENTRYPOINT | 容器启动的入口;可追加外部的命令;可接收[CMD]项为参数 |
CMD 与 ENTRYPOINT 的关系
CMD 指令可以设置容器创建时执行的默认命令。应将命令写在数组中,数组中每个元素为命令的每个单词。
如:CMD ['ls', '-l'],最终执行的完整命令:ls -l
CMD 也会被创建容器 RUN <image>:<tag> 之后的参数覆盖。
如:docker run <image> ip addr,最终执行的完整命令:ip addr
ENTRYPOINT非必须,通常会放入命令或.sh文件,表示进入后首先执行的动作。可被 --entrypoint 参数覆盖。
有 ENTRYPOINT 时,CMD 拼接到 ENTRYPOINT 命令行尾部,合并一起执行。
如:CMD ['-s'],ENTRYPOINT ['ip addr'],最终执行的完整命令:ip addr -s
有 ENTRYPOINT 时,RUN <image>:<tag> 之后有参数-V时,覆盖CMD后合并执行。
如:CMD ['-s'],ENTRYPOINT ['ip addr'],最终执行的完整命令:ip addr -V
3.7 Dockerfile 制作镜像案例
制作一个 mysql-router 的镜像文件
创建空文件夹,作为制作镜像的根目录,文件夹中创建Dockerfile文件:touch Dockerfile
Dockerfile 内容如下:
# 基于 Oracle 9 Linux 系统的依赖
FROM oraclelinux:9-slim
# 系统默认字符集
ENV LANG C.utf8
# 系统默认时区
ENV TZ Asia/Shanghai
# mysql-router 用到的集群 Master Uri 作为系统变量
# 集群 Master Uri 格式为:{user}:{pass}@{host}:{port}
ENV MASTER_URI user:pass@host:port
# 以下运行在指定账户下
USER root
# 进入系统后的默认目录
WORKDIR ~
# 制作系统所需的命令步骤
# - 网络安装MySQL官网提供的 Yum Repository,编译 mysql-router 在此 Repo 下安装
RUN set -e; rpm -ivh https://repo.mysql.com/mysql80-community-release-el9-1.noarch.rpm
RUN set -e; microdnf clean all
RUN set -e; microdnf makecache
RUN set -e; microdnf install mysql-router-community-8.0.31 -y
# 对外提供 mysql-router 的读写端口
EXPOSE 6446 6447
# mysql-router 初始化 并 启动
ENTRYPOINT mysqlrouter --bootstrap $MASTER_URI -u=root --force && mysqlrouter -u=root
Dockerfile文件保存退出后,在此目录下执行 build 命令,生成 image 包。
# build 格式:docker build -t {image-name}:{tag} {根目录}
docker build -t mysql/router8:1.0 .
# 查看 image list
docker image ls
mysql/router8 Image 运行到容器
docker run -dit \
--restart unless-stopped \ # 非手动关机时自动重启
--name mysql.clus.mr \ # 容器名称
--hostname mr \ # 计算机名
--network br.mysql.clus \ # 指定网络
--ip 12.12.0.5 \ # 集群时建议使用固定IP
-p 6446:6446 -p 6447:6447 \ # 对外开发的端口映射
-v /my/mr.hosts:/etc/hosts \ # 集群时的 hosts 优化
-e MASTER_URI=root:sa.@mc2:3306 \ # 集群master地址
mysql/router8:1.0 # 使用的镜像
# 客户端连接MySQL测试
mysql -h mr -u root -P 6646 -p
3.8 Dockerfile 编写注意事项
容器只启动运行一个进程
从技术角度讲,Docker容器中可以运行多个进程。但跟未使用容器前没太大区别,构建时间变长,镜像体积大,横向扩展时浪费资源。
不建议在构建中升级版本
为了降低复杂性、减少依赖、减小文件大小、节约构建时间,应该避免安装任何不必要的包。
显示指定FROM标签
无标签时默认LATEST,有可能版本被切换,不一定能兼容后续应用。指定标签避免此类问题的发生。
删除多余的文件
假设新安装了一些软件包,它们都保存在/var/lib/apt/lists/目录中,但在运行时并不需要,删除无用的文件减少镜像大小。
选择合适的基础镜像
如 FROM ubuntu 作为基础镜像。但是只需要运行node程序,没有必要使用一个通用的基础镜像,针对node镜像应该是更好的选择。
或者使用任何镜像的 alpine 版,alpine是一个极小化的Linux发行版,只有4MB,这让它非常适合作为基础镜像。
设置WORKDIR
WORKDIR 指令可以设置默认目录,也就是运行 RUN / CMD / ENTRYPOINT 指令的地方。
优先使用COPY
ADD相对复杂一些
合理调整COPY与RUN的顺序,合理拆分RUN指令
每行指令在镜像中都代表一个镜像层,将变化最少的部分放在 Dockerfile 的前面,这样可以充分利用镜像缓存。
比如:先仅需一次的 RUN apt-get update && apt-get install -y node.js;再可能多次代码更新的 COPY . /app。
设置默认的环境变量、映射端口和数据库逻辑卷
ENV LANG C.utf8 设置默认
ENV TZ Asia/Shanghai 设置默认
ENV PROJECT_DIR=/app 设置新变量
WORKDIR $PROJECT_DIR 应用变量
COPY ./ $PROJECT_DIR 应用变量
使用LABEL设置镜像详情(元数据)
与 BASE 覆盖/追加。如 LABEL com.example.version="0.0.1-beta"
使用HEALTHCHECK健康检测
HEALTHCHECK --interval=5s --timeout=5s --retries=5 CMD curl --fail http://localhost:80 || exit 1
编写.dockerignore文件
与 Dockerfile 同目录,设置 Build 打包时可忽略的文件。
如下文件内容:指定文件夹.git 和后缀 .md 的文件
.git
*.md
四、服务管理
4.1 Compose
# 编排服务 批量管理
4.2 Machine
# 客户端工具
4.3 Swarm
# 集群管理工具
五、可视化管理工具
告别命令行 - Portainer:https://www.portainer.io/
六、经验
容器内访问外部主机IP
网关在外部主机上运行,内部网关地址和外部主机IP指向的是同一台机器,容器内访问网关地址172.17.0.1,等于访问了外部主机IP。
方式一:直接用网关地址172.17.0.1,内外通用;比如:外部命令 ip addr 列出了包含网关地址的所有IP。
方式二:容器内hosts手动追加别名,用别名访问
方式三:创建容器时参数 docker run --add-host={自定义名称}:host-gateway
相当于容器内hosts手动追加的过程
上图:hosts内,将自定义名称 与 host-gateway网关地址172.17.0.1 绑定。
作者:Sol·wang - 博客园
出处:https://www.cnblogs.com/Sol-wang/p/17063192.html
声明:本文版权归作者和[博客园]共有,未经作者同意,不得转载。