Docker入门笔记

本文最后更新于:2022年10月17日 下午

Docker入门笔记

我入门Docker的笔记,基本都是网上各路搜集来的资料,包含了Docker的解释、安装和使用。

什么是Docker

Docker overview | Docker Documentation

什么是Docker?看这一篇干货文章就够了! - 知乎 (zhihu.com)

Docker是一种实现容器化的技术,在一个OS上运行的多个容器能够共享资源,从而增加资源使用率,并大幅提升启动速度(相较于虚拟机)。使用Docker还能将应用程序和运行软硬件环境分离开,从而实现应用程序的快速交付,不需要太多关心程序运行的环境配置,即“build once, run everywhere”。

Docker的架构如下图,是一种C/S架构。首先需要编写一个Dockerfile,在使用docker build命令对其进行编译之后,就能得到Image(镜像)。Dockerfile包含了构建镜像的信息,比如基于的是什么系统/镜像、要安装哪些程序、要包含哪些文件、要运行什么命令等等,而docker build就相当于编译,而Image就是编译出来的“可执行”的文件。

在有了Image之后,通过docker run就能将其加载到内存中运行,执行之后就成为了一个container。

为了不重复造轮子,可以将自己编译的Image上传到Registry中分享给其他人,官方有公共的Docker Hub。使用docker pull就能从Registry上下载镜像了,同时也能使用docker push 将自己的Image上传。

architecture

在Ubuntu安装Docker

如何在 Ubuntu 20.04 上安装和使用 Docker - 知乎 (zhihu.com)

Install Docker Engine on Ubuntu | Docker Documentation

下面的安装过程基本就是copy官方教程,安装过程需要sudo

1
2
3
4
5
6
7
8
9
10
# 1. 更新apt索引,并为HTTPS下载做准备
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg lsb-release
# 2. 添加Docker官方GPG key
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# 3. 添加下载源
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 4. 下载安装
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin

卸载Docker

1
2
3
4
5
# *卸载
sudo apt-get purge docker-ce docker-ce-cli containerd.io docker-compose-plugin
# *删除Image Container Volume等配置
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd

无root权限用户运行docker

Running Docker Without sudo | Baeldung on Linux

Post-installation steps for Linux | Docker Documentation

1
2
3
4
5
6
# 添加一个用户组docker
sudo groupadd docker
# 将现在这个登录用户添加到docker用户组
sudo usermod -aG docker $USER
# 登入另一个用户组,在使用docker时要保证是docker用户组下
newgrp docker

假如运行提示了以下信息,则是因为~/.docker/目录在之前通过sudo权限创建了,可以删除这个目录(会丢失已有的配置)或者改变这个目录的权限。

1
2
3
4
5
6
7
8
# WARNING: Error loading config file: /home/user/.docker/config.json -
# stat /home/user/.docker/config.json: permission denied

# 改变权限
# 将目标用户下的.docker目录改成它自己的
sudo chown "$USER":"$USER" /home/"$USER"/.docker -R
# 然后选择g(文件所有者所在组) +(增加权限) rwx(read write execute权限)
sudo chmod g+rwx "$HOME/.docker" -R

安装之后验证

1
docker container run hello-world

Dockerfile格式

Dockerfile reference | Docker Documentation

Dockerfile中,注释用#,命令是一些单词的大写, 分行可以用\

  1. FROM

    Dockerfile的第一个命令必须是FROM命令,设置基础镜像

  2. RUN

    在当前镜像上新建一个层并执行命令(于docker build阶段),有两种模式:

    1
    2
    RUN <command>
    RUN ["executable", "param1", "param2"]

    由于每一个RUN都会新建一个层,所以可以通过&&连接命令来避免创建过多的层。

  3. CMD

    启动容器时(docker run)执行的命令,只能有一条,有三种模式:

    1
    2
    3
    CMD ["executable","param1","param2"]
    CMD ["param1","param2"] # 用这种方式需要指定`ENTRYPOINT
    CMD command param1 param2
  4. ENTRYPOINT

    CMD一样是在启动容器时运行,有两种格式:

    1
    2
    ENTRYPOINT ["executable", "param1", "param2"]
    ENTRYPOINT command param1 param2

    假如提供了CMD,那执行时会变成<ENTRYPOINT> <CMD>

  5. LABEL

    给镜像添加一些元信息,比如开发日期、维护者信息、版本等,采用键值对的形式:

    LABEL <key>=<value> <key>=<value> <key>=<value> ...

  6. EXPOSE

    指定运行时监听的端口和协议,可以暴露多个端口,默认TCP

    EXPOSE <port>/<protocol>

    但是这个也能在docker run中使用-p参数覆盖:

    docker run -p 80:80/tcp -p 80:80/udp ...

  7. ENV

    设置环境变量,也可以在docker run中使用--env参数覆盖,可以用来设置数据库密码等

    1
    2
    3
    4
    5
    6
    # dockerfile中
    ENV MY_NAME="John Doe"
    ENV MY_DOG=Rex\ The\ Dog
    ENV MY_CAT=fluffy
    # 命令行覆盖
    docker run --env <key>=<value>
  8. ADD

    将文件添加进镜像中,有两种格式,src可以是远程URL的资源或者本地的资源:

    1
    2
    ADD [--chown=<user>:<group>] <src>... <dest>
    ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]
    1
    2
    3
    4
    # 不安装git来添加一个github库
    # syntax=docker/dockerfile-upstream:master-labs
    FROM alpine
    ADD --keep-git-dir=true https://github.com/moby/buildkit.git#v0.10.1 /buildkit
  9. COPY

    ADD一样,但是只能添加本地资源。

  10. VOLUME

    挂载一个数据目录,可能是数据库的本地保存目录,以免容器重启而丢失或者容器变得很大。默认会保存在/var/lib/docker/volumes/{ID}

    命令格式为:VOLUME ["/data"]

    在运行容器时,也有-v参数来挂载数据目录:

    1
    2
    # 将容器中/soft目录挂载到主机的/test下,容器中对/soft的写入会写在主机的/test下。
    docker run -v /test:/soft

    关于Docker目录挂载的总结 - iVictor - 博客园 (cnblogs.com)

  11. USER

    设置用户名和用户组,格式USER <user>[:<group>]

  12. WORKDIR

    设置工作目录,类似cd命令,格式WORKDIR /path/to/workdir

  13. ARG

    声明一些变量,在build期间通过--build-arg <varname>=<value>来设置值,不建议通过这种方式传递秘钥,因为能通过docker history查看。

    格式:ARG <name>[=<default value>]

可以参考微信云托管的flask框架的Dockerfile:wxcloudrun-flask/Dockerfile at main · WeixinCloud/wxcloudrun-flask (github.com)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 二开推荐阅读[如何提高项目构建效率](https://developers.weixin.qq.com/miniprogram/dev/wxcloudrun/src/scene/build/speed.html)
# 选择基础镜像。如需更换,请到[dockerhub官方仓库](https://hub.docker.com/_/python?tab=tags)自行选择后替换。
# 已知alpine镜像与pytorch有兼容性问题会导致构建失败,如需使用pytorch请务必按需更换基础镜像。
FROM alpine:3.13

# 容器默认时区为UTC,如需使用上海时间请启用以下时区设置命令
# RUN apk add tzdata && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo Asia/Shanghai > /etc/timezone

# 使用 HTTPS 协议访问容器云调用证书安装
RUN apk add ca-certificates

# 安装依赖包,如需其他依赖包,请到alpine依赖包管理(https://pkgs.alpinelinux.org/packages?name=php8*imagick*&branch=v3.13)查找。
# 选用国内镜像源以提高下载速度
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tencent.com/g' /etc/apk/repositories \
# 安装python3
&& apk add --update --no-cache python3 py3-pip \
&& rm -rf /var/cache/apk/*

# 拷贝当前项目到/app目录下(.dockerignore中文件除外)
COPY . /app

# 设定当前的工作目录
WORKDIR /app

# 安装依赖到指定的/install文件夹
# 选用国内镜像源以提高下载速度
RUN pip config set global.index-url http://mirrors.cloud.tencent.com/pypi/simple \
&& pip config set global.trusted-host mirrors.cloud.tencent.com \
&& pip install --upgrade pip \
# pip install scipy 等数学包失败,可使用 apk add py3-scipy 进行, 参考安装 https://pkgs.alpinelinux.org/packages?name=py3-scipy&branch=v3.13
&& pip install --user -r requirements.txt

# 暴露端口。
# 此处端口必须与「服务设置」-「流水线」以及「手动上传代码包」部署时填写的端口一致,否则会部署失败。
EXPOSE 80

# 执行启动命令
# 写多行独立的CMD命令是错误写法!只有最后一行CMD命令会被执行,之前的都会被忽略,导致业务报错。
# 请参考[Docker官方文档之CMD命令](https://docs.docker.com/engine/reference/builder/#cmd)
CMD ["python3", "run.py", "0.0.0.0", "80"]