介绍

  • 这里列出本人常用的docker操作
  • 部分图片来源网络
  • 本教程所有内容均在Ubuntu上操作,正常情况下所有Linux系统基本通用
  • 本教程若未说明,全部是在root用户下执行命令,如果是普通用户执行,则需要在命令前面添加sudo进行提权,这里不细究

配置相关

Docker的配置文件是/etc/docker/daemon.json,如果没有则手动创建即可,创建后重启docker进行生效:
systemctl restart docker
该配置文件是josn格式,这里举例常用的个别配置,其他配置去官网或者找其他教程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"experimental": true,
"registry-mirrors": [
"https://dockerproxy.com",
"https://docker.mirrors.ustc.edu.cn",
"https://docker.nju.edu.cn"
],
"proxies": {
"http-proxy": "http://proxy.example.com:3128",
"https-proxy": "https://proxy.example.com:3129",
"no-proxy": "*.test.example.com,.example.org,127.0.0.0/8"
},
"data-root": "/opt/docker"
}

说明:

字段 说明
experimental 该参数可以使docker拉取其他架构的镜像,一般用不到
registry-mirrors 配置镜像源,但从2024-06-06开始,国内镜像加速服务逐步停止,只能用魔法了
可以参考这位大佬的帖子Docker Hub 镜像加速器
proxies 配置代理,但是注意只有Docker engine版本在23.0以及之后才支持这个参数
如果需要使用socks5的代理,只需要将代理链接改成socks5即可,详见参考
data-root 配置docker的数据目录,如果不设置,默认为/var/lib/docker

基本操作

这里用ubuntu的系统镜像举例

  • 查看docker生效的信息
    docker info
  • 搜索镜像
    docker search ubuntu
  • 拉取/下载/更新镜像
    docker pull ubuntu
    这里注意:更新镜像同样使用这个命令,并且如果有新镜像被下载后,旧的latest版本镜像的版本号会变为<none>
    这种情况下只需要停掉已经拉起的镜像,然后通过id号删除该旧镜像即可,然后再拉起新的镜像使用
    Update Images
  • 删除镜像
    docker rmi ubuntu
    注意:删除镜像前提是当前没有拉起该镜像,也就是没有这个镜像对应的实例才可以删除。当然也可以使用-f参数强制删除
    docker rmi -f ubuntu
  • 运行镜像/拉起镜像实例
    通过latest版本的ubuntu镜像创建名为ubos的镜像实例并运行,而且使用/bin/bash/进入该镜像命令行
    docker run -it --name ubos ubuntu:latest /bin/bash
    通过latest版本的ubuntu镜像创建名为ubos的镜像实例并运行,而且放在后台运行
    docker run -d --name ubos ubuntu:latest
    其他常用参数:
    • -v 绑定文件或者文件夹,例如-v /opt:/mnt会将系统上/opt目录和镜像实例里的/mnt目录做绑定
      该参数为强绑定,如果双方没有对应目录/文件则会强制创建该目录/文件
      与其对应的弱绑定为--bind参数,用法相同,但是没有对应目录会报错
    • -p 绑定/映射端口
  • 更新实例参数
    如果在创建镜像实例的时候写错了或者忘记设置参数,可以通过update命令进行更新参数
    例如更新--restart参数
    docker update --restart=always ubos
    PS:这里列举下restart参数的值
    • no 默认值,当实例退出后不会重启该实例,例如重启系统后不会自动拉起
    • on-failure[:time] 如果实例是异常退出,也就是返回状态为非0,则会重启容器,后面time是可选的重启次数,超过一定次数后则不会再尝试拉起
    • always 当实例退出后会再次拉起,当然如果是手动退出,则会在下次docker启动时自动拉起
    • unless-stopped 与always类似,但是区别是如果手动退出,下次docker启动时就不会去拉起
  • 查看当前运行的镜像实例
    docker ps
    查询创建的镜像实例的id
    docker ps -q
    查看创建的所有镜像实例
    docker ps -a
  • 停止镜像实例
    docker stop ubos
  • 启动镜像实例
    docker start ubos
  • 进入当前正在运行的镜像实例
    docker exec -it ubos /bin/bash
  • 删除镜像实例
    docker rm ubos
    如果没有停止镜像实例,则无法直接删除,可以通过-f参数进行强制删除
    docker rm -f ubos

高级操作

代理配置

因为国内网络环境的原因,在docker中需要下载各种组件有时候会异常艰难,如果需要配置docker走代理,可以按如下操作
这里存在三种场景:

  1. Docker自身代理 用来拉取镜像
  2. Container内容器代理 容器内特殊网络访问
  3. docker build代理 创建镜像时期的代理

这里有两种配置方法,配置到service服务里或者写入docker的配置文件里,二选一即可

  • 配置到service服务里

    1. 首先创建一个服务目录
      1
      sudo mkdir -p /etc/systemd/system/docker.service.d
    2. 创建一个配置文件/etc/systemd/system/docker.service.d/http-proxy.conf并写入内容
      1
      2
      3
      4
      [Service]
      Environment="HTTP_PROXY=http://proxy.example.com:3128"
      Environment="HTTPS_PROXY=https://proxy.example.com:3129"
      Environment="NO_PROXY=localhost,127.0.0.1,docker-registry.example.com,.corp"

      修改配置文件后需要刷新配置和重启docker服务生效

      1
      2
      sudo systemctl daemon-reload
      sudo systemctl restart docker

      可以通过这个命令进行检查

      1
      sudo systemctl show --property=Environment docker
  • 写入docker的配置文件里
    配置文件是/etc/docker/daemon.json

    1
    2
    3
    4
    5
    6
    7
    {
    "proxies": {
    "http-proxy": "http://proxy.example.com:3128",
    "https-proxy": "https://proxy.example.com:3129",
    "no-proxy": "*.test.example.com,.example.org,127.0.0.0/8"
    }
    }

    修改配置文件后需要重启docker服务生效

    1
    sudo systemctl restart docker

容器内可以按照容器自身的方式配置代理,也可以通过docker来配置代理
需要配置~/.docker/config.json,以下配置,只在Docker 17.07及以上版本生效

1
2
3
4
5
6
7
8
9
{
"proxies": {
"default": {
"httpProxy": "http://proxy.example.com:3128",
"httpsProxy": "https://proxy.example.com:3129",
"noProxy": "*.test.example.com,.example.org,127.0.0.0/8"
}
}
}

配置完成后对下次拉起的容器生效

创建docker镜像时一些场景也需要特殊网络,可以通过参数进行解决

1
2
3
4
5
docker build . \
--build-arg "HTTP_PROXY=http://proxy.example.com:8080/" \
--build-arg "HTTPS_PROXY=http://proxy.example.com:8080/" \
--build-arg "NO_PROXY=localhost,127.0.0.1,.example.com" \
-t your/image:tag

无论是 docker run 还是 docker build,默认是网络隔绝的。如果代理使用的是 localhost:3128 这类,则会无效。这类仅限本地的代理,必须加上--network host才能正常使用。而一般则需要配置代理的外部IP,而且代理本身要开启 Gateway 模式。

部分查询操作

  • 查看镜像实例的日志
    docker logs ubos
  • 查看镜像的架构信息
    docker image inspect ubuntu | grep Arch

下载其他架构的镜像

这里有个前提,就是配置文件中必须配置experimental参数为true才能下载其他架构的镜像
确认参数没有问题后通过--platform来指定架构

  • 下载x86_64架构的ubuntu镜像
    docker pull --platform linux/amd64 ubuntu:latest
  • 下载arm64架构的ubuntu镜像
    docker pull --platform linux/arm64 ubuntu:latest

镜像的导出和导入

这里用ubuntu的最新版本举例:ubuntu:latest

导出

  • 导出镜像打包为tar文件
    docker save -o out_ubuntu.tar ubuntu:latest
  • 然后得到的tar文件就是导出的镜像,可以通过压缩命令缩小其体积

导入

  • 将导出的tar包镜像导入到docker
    docker load -i out_ubuntu.tar

制作镜像

通过Dockerfile创建镜像

通过Dockerfile的方式创建镜像在这里不细说,网上教程非常多,这里因为完整性列出来常用命令:

指令 含义
FROM 镜像 指定新镜像所基于的镜像,第一条指令必须为FROM指令,每创建一个镜像就需要一条FROM指令
MAINTAINER 名字 说明新镜像的维护人信息
RUN 命令 在所基于的镜像上执行命令,并提交到新的镜像中
CMD [“要运行的程序”,“参数1”,“参数2”] 指令启动容器时要运行的命令或脚本
ENTRYPOINT [“要运行的程序”,“参数1”,“参数2”] 与CMD相似,但是只能有一个并且不会被docker run命令行参数覆盖
COPY 源文件/目录 目标文件/目录 将本地主机上得文件/目录复制到目标地点,源文件/目录要与Dockerfile在相同的目录中
ADD 源文件/目录 目标文件/目录 将源文件复制到目标文件,源文件要与Dockerfile位于相同目录中,或者是一个URL
ENV 环境变量 变量值 设置一个环境变量的值,会被后面的RUN使用
ARG 定义构建时的变量,可以通过 –build-arg 参数传递
EXPOSE 端口号 指定新镜像加载到Docker时要开启端口
VOLUME [“目录”] 在容器中创建一个挂载点
USER 用户名/UID 指定运行容器时的用户
WORKDIR 路径 为后续的RUN、CMD、ENTRYPOINT指定工作目录
ONBUILD 命令 指定所生成的镜像作为一个基础镜像时所要运行的命令
HEALTHCHECK 健康检查
LABEL 标签 为镜像添加元数据信息

这里说明下什么情况下会创建新层级
结论:只有修改了文件系统的命令才会产生新的镜像层
比如 ADD 命令是添加文件到镜像中,肯定修改了文件系统,所以它会创建新层
而CMD、LABEL等只修改镜像元数据的命令均不会创建新的镜像层
简单理解可以说是导致镜像里操作文件的命令就会创建新层级

创建建议:

  • 因为层级关系,每多一层会导致镜像体积增大,所以尽可能的要减少触发层级命令,比如同一类执行的命令尽可能全部写在一条
  • 可以通过命令删除不用的内容来减少体积

以创建samba镜像为例

1
2
3
4
5
6
7
8
9
10
FROM ubuntu

RUN apt-get update \
&& apt-get install -y samba \
&& useradd smbusr -u 1100 -s /usr/sbin/nologin \
&& rm -rf /var/lib/apt/lists/*

EXPOSE 139/tcp 445/tcp
CMD ["/usr/share/samba/update-apparmor-samba-profile"]
CMD ["/usr/sbin/smbd", "--foreground", "--no-process-group"]

通过现有的实例创建镜像

该方法一般用途是已经拉起来了实例,然后在实例里做了写特有的修改配置,接着要创建成自己的新镜像方便使用

  • 如何拉起镜像并且操作这里不赘述
  • 将实例提交成新的镜像
    docker commit [参数] 实例id或者实例名称 新镜像名称:版本
    这里的选项可以有
    • -m 说明
    • -a 作者
    • -p 生成镜像过程中停止实例的运行
      例如将ubos提交成新的myub,并且是最后版本
      docker commit ubos myub:latest

通过iso来创建镜像

这个方法如果你不懂linux,估计会遇到各种问题,加油!

  • 与其说是通过iso来创建,不如说是通过当前系统来创建
  • 其本质是将当前系统重要目录打包成tar文件,然后通过import命令做成镜像
  • 操作方法:
    • 如果是iso,则需要从iso启动,用iso的好处是没有冗余文件,体积比较小(但是和官方镜像比起来还是大很多)
    • 然后创建一个目录,将根分区挂载到这个目录下(这里要注意如果你的usr、var等关键分区是单独的,则也需要挂载过去)
      mkdir sysdir
      mount /dev/xxx sysdir 这里的xxx就是你的根分区对应的设备
    • 然后通过tar命令将该目录打包
      tar -cpf mysys.tar --directory=./sysdir .
    • 接着将该tar包导入docker做成镜像
      cat mysys.tar | docker import - mysys:latest
      通过该方式中间同样有很多灵活性,比如可修改自己任何文件,也可以删除不必要的内容以减少体积
      当然也可以直接使用大佬们的脚本进行创建
      github contrib

注意事项

  • 权限问题:
    如果正常进入docker实例进行操作报错没有权限,可以通过--privileged=true参数进行提权

参考