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 绑定。

posted @ 2023-01-20 20:05  Sol·wang  阅读(322)  评论(0编辑  收藏  举报