Docker 是一个开源的**应用容器引擎**,基于 Go 语言开发。Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。 文档部分内容来自[Docker 教程 | 菜鸟教程](https://www.runoob.com/docker/docker-tutorial.html) ## 一、C/S架构 Docker 采用**客户端-服务器(C/S)架构**。核心组件是 **Docker 客户端** 和 **Docker 守护进程**。守护进程负责繁重的工作,如构建、运行和分发容器。客户端和守护进程可以运行在同一个系统上,也可以让客户端连接远程的守护进程。 ##### 1、架构图  #### 2、Docker 客户端 **角色**:用户与 Docker 交互的主要方式。 **功能**:当你使用 `docker run`、`docker build` 等命令时,客户端会将这些命令通过 **Docker API** 发送给 **Docker 守护进程**。 **特点**:一个客户端可以与多个守护进程通信。 #### 3、Docker 守护进程 **角色**:Docker 架构的“大脑”,是一个在后台运行的长寿命程序(通常在主机上以 `dockerd` 进程形式存在)。 **功能**: - 监听 Docker API 请求。 - 管理 Docker 的核心对象:**镜像**、**容器**、**网络**、**数据卷**。 - 与其他守护进程通信以管理 Docker 服务(在 Swarm 模式下)。 #### 4、Docker 核心对象(由守护进程管理) **镜像**:一个**只读模板**,带有创建 Docker 容器的指令。它类似于面向对象编程中的“类”。镜像通常基于其他镜像构建,并添加额外的定制层。例如,你可能会有一个基于 `ubuntu` 镜像的镜像,但安装了 Nginx 和你的应用程序代码。 **容器**:镜像的一个**可运行实例**。你可以使用 Docker API 或 CLI 创建、启动、停止、移动或删除容器。容器与镜像的关系,就像面向对象中“对象”与“类”的关系。容器是轻量级的,因为它默认只包含运行应用程序所需的进程和资源。 **网络**:Docker 提供了强大的网络功能,允许容器之间、容器与外部世界进行通信。可以创建自定义网络,将容器连接到特定网络中以实现隔离或互通。常见的网络驱动有 `bridge`(默认)、`host`、`overlay`(用于 Swarm 集群)等。 **数据卷**:用于持久化容器产生的数据以及容器间共享数据的机制。容器本身是临时的,当容器被删除,其内部的文件系统也会被销毁。数据卷将容器内的特定路径**映射**到主机上的一个目录,从而实现数据的持久化存储。 #### 5、Docker 镜像仓库 **角色**:存储和分发 Docker 镜像的服务。 **功能**: - **拉取镜像**:当您执行 `docker pull ubuntu` 时,Docker 客户端会指示守护进程从配置的镜像仓库(默认为 Docker Hub)拉取 `ubuntu` 镜像。 - **推送镜像**:当你构建了自己的镜像后,可以使用 `docker push` 命令将其推送到镜像仓库(公共或私有)以供他人使用。 **类型**: - **公共仓库**:如 **Docker Hub**,是默认的公共仓库,包含了大量官方和个人发布的镜像。 - **私有仓库**:如 Harbor、Nexus Repository,可以在公司内网搭建,用于存储私有镜像,保证代码安全和交付速度。 ## 二、安装Docker #### 1、脚本安装 使用Linux系统进行安装,测试系统版本为Ubuntu22.04 ```bash # 下载并执行Docker官方安装脚本 curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh ``` 安装成功后如图  #### 2、启动服务 ```bash # 启动Docker服务 sudo systemctl enable docker sudo systemctl start docker ``` #### 3、卸载Docker ```bash # 删除安装包 sudo apt-get purge docker-ce # 删除镜像、容器、配置文件等内容 sudo rm -rf /var/lib/docker ``` ## 三、使用Docker #### 1、HelloWorld Docker 允许你在容器内运行应用程序, 使用 `docker run` 命令来在容器内运行一个应用程序。 ```bash docker run ubuntu:22.04 /bin/echo "Hello world" ``` - `docker`:Docker 的二进制执行文件 - `run`:与前面的 docker 组合来运行一个容器 - ubuntu:22.04`:指定要运行的镜像,Docker 首先从本地主机上查找镜像是否存在,如果不存在,Docker 就会从镜像仓库 Docker Hub 下载公共镜像 - `/bin/echo "Hello world"`:在启动的容器里执行的命令  #### 2、交互式容器 通过 docker 的两个参数 `-i` `-t`,让 docker 运行的容器实现"对话"的能力 ```bash docker run -i -t ubuntu:22.04 /bin/bash ``` - `-t`:在新容器内指定一个伪终端或终端 - `-i`:允许你对容器内的标准输入 (STDIN) 进行交互  注意第二行 `root@0d11ad791a32:/#` ,此时我们已进入一个 ubuntu22.04 系统的容器 可以尝试在容器中运行命令 `cat /proc/version`和`ls`分别查看当前系统的版本信息和当前目录下的文件列表  可以通过运行 `exit` 命令或者使用 `CTRL+D` 来退出容器  #### 3、进程式容器 ##### 启动容器 使用命令`-d`参数创建一个以后台进程方式运行的容器,会返回输出容器的ID ```bash docker run -d ubuntu:22.04 /bin/sh -c "while true; do echo hello world; sleep 100; done" ```  ##### 容器列表 可以通过`docker ps`查看已经创建的容器状态,可以添加`-a`参数查看所有的容器  * `CONTAINER ID`:容器 ID * `IMAGE`:使用的镜像 * `COMMAND`:启动容器时运行的命令 * `CREATED`:容器的创建时间 * `STATUS`:容器状态,容器的状态有7种 - `created`:已创建 - `restarting`:重启中 - `running/Up` :运行中 - `removing`:迁移中 - `paused`:暂停 - `exited`:停止 - `dead`:死亡 * `PORTS`:容器的端口信息和使用的连接类型(tcp\udp) * `NAMES`:自动分配的容器名称 ##### 容器日志 可以通过`docker logs`查看容器内的标准输出,参数可以跟`ID/NAME`  ##### 停止容器 可以通过`docker stop`来停止正在运行中的容器,参数可以跟`ID/NAME`  #### 4、常用命令 | **命令** | **功能** | **示例** | | :-------------------- | :---------------------------------------------- | :----------------------------------------- | | `docker run` | 启动一个新的容器并运行命令 | `docker run -d ubuntu` | | `docker ps` | 列出当前正在运行的容器 | `docker ps` | | `docker ps -a` | 列出所有容器(包括已停止的容器) | `docker ps -a` | | `docker build` | 使用 Dockerfile 构建镜像 | `docker build -t my-image .` | | `docker images` | 列出本地存储的所有镜像 | `docker images` | | `docker pull` | 从 Docker 仓库拉取镜像 | `docker pull ubuntu` | | `docker push` | 将镜像推送到 Docker 仓库 | `docker push my-image` | | `docker exec` | 在运行的容器中执行命令 | `docker exec -it container_name bash` | | `docker stop` | 停止一个或多个容器 | `docker stop container_name` | | `docker start` | 启动已停止的容器 | `docker start container_name` | | `docker restart` | 重启一个容器 | `docker restart container_name` | | `docker rm` | 删除一个或多个容器 | `docker rm container_name` | | `docker rmi` | 删除一个或多个镜像 | `docker rmi my-image` | | `docker logs` | 查看容器的日志 | `docker logs container_name` | | `docker inspect` | 获取容器或镜像的详细信息 | `docker inspect container_name` | | `docker exec -it` | 进入容器的交互式终端 | `docker exec -it container_name /bin/bash` | | `docker network ls` | 列出所有 Docker 网络 | `docker network ls` | | `docker volume ls` | 列出所有 Docker 卷 | `docker volume ls` | | `docker-compose up` | 启动多容器应用(从`docker-compose.yml` 文件) | `docker-compose up` | | `docker-compose down` | 停止并删除由`docker-compose` 启动的容器、网络等 | `docker-compose down` | | `docker info` | 显示 Docker 系统的详细信息 | `docker info` | | `docker version` | 显示 Docker 客户端和守护进程的版本信息 | `docker version` | | `docker stats` | 显示容器的实时资源使用情况 | `docker stats` | | `docker login` | 登录 Docker 仓库 | `docker login` | | `docker logout` | 登出 Docker 仓库 | `docker logout` | **常用选项说明** - **`-d`**:后台运行容器,例如 `docker run -d ubuntu` - **`-it`**:以交互式终端运行容器,例如 `docker exec -it container_name bash` - **`-t`**:为镜像指定标签,例如 `docker build -t my-image` #### 5、容器使用 ##### 查看所有容器 ```bash docker ps -a ```  ##### 启动已停止的容器 ```bash docker start docker restart ```  ##### 进入容器 在使用 `-d` 参数时启动容器时,容器会运行在后台,这时如果要进入容器,可以通过以下命令进入: - `docker attach`:允许你与容器的标准输入(stdin)、输出(stdout)和标准错误(stderr)进行交互 - `docker exec`:推荐使用 `docker exec` 命令,因为此命令会退出容器终端,但不会导致容器的停止 `docker attach`  **注意**:如果从这个容器退出,会导致容器的停止。 `docker exec` 该命令需要至少 2 个参数 ```bash docker exec -it <命令> ```  ##### 导出容器 默认的导出目录为当前命令运行的目录 ```bash docker export > filename.tar ```  ##### 导入容器快照 ```bash docker import ```  ##### 删除容器 删除单个容器 ```bash docker rm ``` **注意**:要删除的容器必须为已停止的容器  删除所有已停止容器 ```bash docker container prune ``` ##### 端口映射 在docker容器中运行一个 Python Flask 应用来运行一个web应用 ```bash # 拉取镜像 docker pull nginx # 创建目录 mkdir -p /www/wwwroot/test # 运行容器 docker run -d -p 80:80 -v /www/wwwroot/test:/usr/share/nginx/html nginx ``` - `-d`:让容器在后台运行 - `-p <主机>:<容器>`:将容器内部使用的网络端口映射到主机上 - `-v <主机>:<容器>`:将主机的目录挂载到容器中  将测试`index.html`文件上传到`/www/wwwroot/test` ```html Hello world 你好,世界 ``` 访问当前主机IP地址,本地测试可以访问`localhost`或者`127.0.0.1`  ##### 查看容器端口 ```html docker port ```  同样的可以通过`docker logs -f `来查看流式标准输出  #### 6、镜像使用 ##### 镜像列表 ```bash docker images ```  - `IMAGE`:表示镜像的名称 - `ID`:镜像ID - `DISK USAGE`:镜像占用磁盘大小 - `CONTENT SIZE`:镜像内容大小 - `EXTRA`:镜像使用状态 ##### 拉取镜像 ```bash docker pull ```  ##### 搜索镜像 可以从 Docker Hub 网站来搜索镜像,Docker Hub 网址为: https://hub.docker.com/ ```bash docker search ```  * `NAME`:镜像仓库源的名称 * `DESCRIPTION`:镜像的描述 * `OFFICIAL`:是否 docker 官方发布 * `stars`:类似 Github 里面的 star,表示点赞、喜欢的意思 ##### 删除本地镜像 ```bash docker rmi ```  ##### 更新(提交)镜像 通过镜像创建的容器后,在容器内进行操作后想要保存成镜像就需要提交镜像更新 ```bash docker commit -m="描述" -a="作者" <容器ID> ```  ##### 构建镜像 从零构建镜像需要使用到`Dockerfile`文件,其中包含一组指令来告诉 Docker 如何构建我们的镜像 在当前目录下创建一个`Dockerfile` ```dockerfile FROM centos:6.7 MAINTAINER Fisher "fisher@sudops.com" RUN /bin/echo 'root:123456' |chpasswd RUN useradd doooog RUN /bin/echo 'doooog:123456' |chpasswd RUN /bin/echo -e "LANG=\"en_US.UTF-8\"" >/etc/default/local EXPOSE 22 EXPOSE 80 CMD /usr/sbin/sshd -D ``` 使用`docker build`构建镜像 ```bash docker build -t doooog/centos:6.7 . ``` - `-t` :指定要创建的目标镜像名 - `.` :Dockerfile 文件所在目录,可以指定Dockerfile 的绝对路径  通过`docker images`查看镜像列表,并通过`docker run -t -i doooog/centos:6.7 /bin/bash`创建容器  ##### 推送镜像 用户登录后,可以通过 `docker push` 命令将自己的镜像推送到 Docker Hub。 ```bash docker push ``` ## 四、容器互联 端口映射并不是唯一把 docker 连接到另一个容器的方法。 docker 有一个连接系统允许将多个容器连接在一起,共享连接信息,docker 连接会创建一个父子关系,其中父容器可以看到子容器的信息。 #### 1、新建网络 ```bash docker network create -d bridge ``` * `-d`:参数指定 Docker 网络类型,有 `bridge`、`overlay`。 可以通过`docker network ls`来查看已经建立的网络  #### 2、连接容器 ```bash # 创建容器1 docker run -itd --name test1 --network test-net ubuntu:22.04 /bin/bash # 创建容器2 docker run -itd --name test2 --network test-net ubuntu:22.04 /bin/bash # 进入容器test1 docker exec -it /bin/bash # 更新仓库 apt-get update # 安装ping工具 apt install iputils-ping # ping容器test2 ping test2 ``` * `--name`:对容器自定义命名 * `--network`:将容器连接到网络   #### 3、配置DNS ##### 设置Docker全局DNS 修改宿主机的 `/etc/docker/daemon.json` 文件中增加以下内容来设置全部容器的DNS,启动容器的 DNS 会自动配置为 `114.114.114.114` 和 `8.8.8.8` ```bash { "dns" : [ "114.114.114.114", "8.8.8.8" ] } ``` **注意**:需要将docker服务重启才可以生效`sudo systemctl restart docker` ##### 容器指定DNS ```bash docker run -it --rm -h <主机名> --dns= --dns-search= ``` * `--rm`:容器退出时自动清理容器内部的文件系统 * `-h HOSTNAME` / `--hostname=HOSTNAME`:设定容器的主机名,它会被写到容器内的 `/etc/hostname` 和 `/etc/hosts` * `--dns=IP_ADDRESS`:添加 DNS 服务器到容器的 `/etc/resolv.conf` 中,让容器用这个服务器来解析所有不在 `/etc/hosts` 中的主机名 * `--dns-search=DOMAIN`: 设定容器的搜索域,当设定搜索域为 `.example.com` 时,在搜索一个名为 `host` 的主机时,DNS 不仅搜索 `host`,还会搜索 `host.example.com` 如果在容器启动时没有指定 `--dns` 和 `--dns-search`,Docker 会默认用宿主主机上的 `/etc/resolv.conf` 来配置容器的 DNS。 ## 五、Dockerfile `Dockerfile` 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明,通过定义一系列命令和参数,Dockerfile 指导 Docker 构建一个自定义的镜像。 #### 1、常用命令 | Dockerfile 指令 | 说明 | | :-------------- | :------------------------------------------------------------------- | | `FROM` | 指定基础镜像,用于后续的指令构建。 | | `MAINTAINER` | 指定Dockerfile的作者/维护者。(已弃用,推荐使用LABEL指令) | | `LABEL` | 添加镜像的元数据,使用键值对的形式。 | | `RUN` | 在构建过程中在镜像中执行命令。 | | `CMD` | 指定容器创建时的默认命令。(可以被覆盖) | | `ENTRYPOINT` | 设置容器创建时的主要命令。(不可被覆盖) | | `EXPOSE` | 声明容器运行时监听的特定网络端口。 | | `ENV` | 在容器内部设置环境变量。 | | `ADD` | 将文件、目录或远程URL复制到镜像中。 | | `COPY` | 将文件或目录复制到镜像中。 | | `VOLUME` | 为容器创建挂载点或声明卷。 | | `WORKDIR` | 设置后续指令的工作目录。 | | `USER` | 指定后续指令的用户上下文。 | | `ARG` | 定义在构建过程中传递给构建器的变量,可使用 "docker build" 命令设置。 | | `ONBUILD` | 当该镜像被用作另一个构建过程的基础时,添加触发器。 | | `STOPSIGNAL` | 设置发送给容器以退出的系统调用信号。 | | `HEALTHCHECK` | 定义周期性检查容器健康状态的命令。 | | `SHELL` | 覆盖Docker中默认的shell,用于RUN、CMD和ENTRYPOINT指令。 | #### 2、FROM 定制的镜像都是基于 FROM 的镜像,后面跟着基于镜像的名称 ```dockerfile FROM ``` #### 3、RUN 用于执行后面跟着的命令行命令 ##### Shell 格式 ```dockerfile RUN <命令行命令> # <命令行命令> 等同于,在终端操作的 shell 命令。 ``` ##### Exec 格式 ```dockerfile RUN ["可执行文件", "参数1", "参数2"] # 例如: # RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php dev offline ``` ##### 注意 Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。例如: ```dockerfile FROM centos RUN yum -y install wget RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" RUN tar -xvf redis.tar.gz ``` 以上执行会创建 `3` 层镜像。可简化为以下格式: ```dockerfile FROM centos RUN yum -y install wget \ && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \ && tar -xvf redis.tar.gz ``` 如上,以 `&&` 符号连接命令,这样执行后,只会创建 `1` 层镜像。 #### 4、COPY 从宿主机复制文件/目录到镜像中 ##### 语法 ```dockerfile COPY [--chown=:] <源路径1>... <目标路径> COPY [--chown=:] ["<源路径1>",... "<目标路径>"] ``` * `[--chown=:]`:可选参数,用户改变复制到容器内文件的拥有者和属组。 * `<源路径>`:源文件或者源目录,这里可以是通配符表达式,其通配符规则要满足 Go 的 filepath.Match 规则。 ##### 示例 ```dockerfile COPY app.py /app/ COPY --chown=node:node . /app ``` #### 5、ADD 类似 COPY,但支持自动解压和 URL 下载 ##### 语法 ```dockerfile ADD [--chown=:] <源路径1>... <目标路径> ADD [--chown=:] ["<源路径1>",... "<目标路径>"] ``` ##### 示例 ```dockerfile ADD https://example.com/file.tar.gz /tmp/ ADD data.tar.gz /app/data/ ``` #### 6、CMD 类似于 RUN 指令,用于运行程序,但二者运行的时间点不同: - `CMD` 在docker run 时运行。 - `RUN` 是在 docker build。 为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。 ##### 语法 ```dockerfile CMD command param1 param2 CMD ["executable","param1","param2"] ``` ##### 示例 ```dockerfile CMD nginx -g 'daemon off;' CMD ["python", "app.py"] ``` #### 7、ENTRYPOINT 类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。 ##### 语法 ```dockerfile ENTRYPOINT command param1 param2 ENTRYPOINT ["executable", "param1", "param2"] ``` ##### 示例 ```dockerfile ENTRYPOINT ["nginx", "-c"] # 定参 CMD ["/etc/nginx/nginx.conf"] # 变参 ``` #### 8、ENV 设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。 ##### 语法 ```dockerfile ENV = ... ``` ##### 示例 ```dockerfile ENV NODE_ENV=production ENV APP_HOME=/app PATH=/usr/local/bin:$PATH ``` #### 9、ARG 构建参数,与 ENV 作用一致。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。 构建命令 docker build 中可以用 `--build-arg <参数名>=<值>` 来覆盖。 ##### 语法 ```dockerfile ARG [=] ``` ##### 示例 ```dockerfile ARG VERSION=latest FROM ubuntu:${VERSION} ``` #### 10、WORKDIR 指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会建立目录。 ##### 语法 ```dockerfile WORKDIR /path/to/workdir ``` ##### 示例 ```dockerfile WORKDIR /app RUN npm install ``` #### 11、USER 用于指定执行后续命令的用户和用户组,这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)。 ##### 语法 ```dockerfile USER <用户名>[:<用户组>] ``` ##### 示例 ```dockerfile USER nobody USER 1000:1000 ``` #### 12、EXPOSE 声明容器运行时监听的端口,帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射,在运行时使用随机端口映射时,也就是 `docker run -P` 时,会自动随机映射 EXPOSE 的端口。 ##### 语法 ```dockerfile EXPOSE [/...] ``` ##### 示例 ```dockerfile EXPOSE 80 EXPOSE 443/tcp 8080/udp ``` #### 13、VOLUME 定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。可以避免重要的数据,因容器重启而丢失,这是非常致命的。 在启动容器 docker run 的时候,我们可以通过 `-v` 参数修改挂载点。 ##### 语法 ```dockerfile VOLUME ["<路径1>", "<路径2>"...] VOLUME <路径> ``` ##### 示例 ```dockerfile VOLUME ["/data", "/logs"] VOLUME /var/lib/mysql ``` #### 14、LABEL LABEL 指令用来给镜像添加一些元数据(metadata),以键值对的形式 ##### 语法 ```dockerfile LABEL = = ... ``` ##### 示例 ```dockerfile LABEL version="1.0" LABEL maintainer="dev@example.com" description="Web app" ``` #### 15、HEALTHCHECK 用于指定某个程序或者指令来监控 docker 容器服务的运行状态。 ##### 语法 ```dockerfile HEALTHCHECK [选项] CMD <命令> # 设置检查容器健康状况的命令 HEALTHCHECK NONE # 如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令 HEALTHCHECK [选项] CMD <命令> # 这边 CMD 后面跟随的命令使用,可以参考 CMD 的用法。 ``` ##### 示例 ```dockerfile HEALTHCHECK --interval=30s --timeout=3s \ CMD curl -f http://localhost/ || exit 1 ``` #### 16、STOPSIGNAL 设置发送给容器以退出的系统调用信号 ##### 语法 ```dockerfile STOPSIGNAL signal ``` ##### 示例 ```dockerfile STOPSIGNAL SIGTERM ``` #### 17、SHELL 覆盖Docker中默认的shell,用于RUN、CMD和ENTRYPOINT指令 ##### 语法 ```dockerfile SHELL ["executable", "parameters"] ``` ##### 示例 ```dockerfile SHELL ["/bin/bash", "-c"] ``` #### 18、ONBUILD 用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜像的过程中不会执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这时执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令。为`子镜像`设置触发指令。 ##### 语法 ```dockerfile ONBUILD ``` ##### 示例 ```dockerfile ONBUILD COPY . /app ONBUILD RUN make build ``` #### 19、AS 为构建阶段的命令取别名 ##### 示例 ```dockerfile FROM node:14 AS build-stage FROM nginx:alpine AS production-stage COPY --from=build-stage /app/dist /usr/share/nginx/html ``` ## 六、Docker Compose Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,可以使用 `YML` 文件来配置应用程序需要的所有服务。 #### 1、安装 ```bash # 下载可执行文件 sudo curl -L "https://github.com/docker/compose/releases/download/v5.0.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose # 赋予可执行权限 sudo chmod +x /usr/local/bin/docker-compose # 创建软链接 sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose # 测试版本 docker-compose version ``` **注意**:安装其他版本仅需更改`v5.0.0`  #### 2、使用示例 ##### 创建测试目录 ```bash mkdir composetest cd composetest ``` ##### 创建`app.py` ```python import time import redis from flask import Flask app = Flask(__name__) cache = redis.Redis(host='redis', port=6379) def get_hit_count(): retries = 5 while True: try: return cache.incr('hits') except redis.exceptions.ConnectionError as exc: if retries == 0: raise exc retries -= 1 time.sleep(0.5) @app.route('/') def hello(): count = get_hit_count() return 'Hello World! I have been seen {} times.\n'.format(count) ``` ##### 创建`requirements.txt` python程序的依赖文件清单 ```python flask redis ``` ##### 创建`Dockerfile` ```dockerfile FROM python:3.7-alpine WORKDIR /code ENV FLASK_APP app.py ENV FLASK_RUN_HOST 0.0.0.0 RUN apk add --no-cache gcc musl-dev linux-headers COPY requirements.txt requirements.txt RUN pip install -r requirements.txt COPY . . CMD ["flask", "run"] ``` - `FROM python:3.7-alpine`: 从 Python 3.7 映像开始构建镜像。 - `WORKDIR /code`: 将工作目录设置为 /code。 - ``` ENV FLASK_APP app.py ENV FLASK_RUN_HOST 0.0.0.0 ``` 设置 flask 命令使用的环境变量。 - `RUN apk add --no-cache gcc musl-dev linux-headers`: 安装 gcc,以便诸如 MarkupSafe 和 SQLAlchemy 之类的 Python 包可以编译加速。 - ``` COPY requirements.txt requirements.txt RUN pip install -r requirements.txt ``` 复制 requirements.txt 并安装 Python 依赖项。 - `COPY . .`: 将 . 项目中的当前目录复制到 . 镜像中的工作目录。 - `CMD ["flask", "run"]`: 容器提供默认的执行命令为:flask run。 ##### 创建`docker-compose.yml` ```yml # yaml 配置 version: '3' services: web: build: . ports: - "5000:5000" redis: image: "redis:alpine" ``` 该 Compose 文件定义了两个服务:web 和 redis。 - `web`:该 web 服务使用从 Dockerfile 当前目录中构建的镜像。然后,它将容器和主机绑定到暴露的端口 5000。此示例服务使用 Flask Web 服务器的默认端口 5000 。 - `redis`:该 redis 服务使用 Docker Hub 的公共 Redis 映像。 ##### 构建镜像与容器 在测试目录中,执行以下命令来启动应用程序: ```bash docker-compose up ``` 在后台执行该服务可以加上 **-d** 参数: ```bash docker-compose up -d ```   访问`ip:5000`本地测试环境可以访问`localhost:5000`或`127.0.0.1:5000`  #### 3、服务定义指令 ##### image 指定容器运行的镜像。以下格式都可以: ```yml image: redis image: ubuntu:14.04 image: tutum/influxdb image: example-registry.com:4000/postgresql image: a4bc65fd # 镜像id ``` 示例 ```yml services: web: image: nginx:1.20 image: redis:alpine ``` ##### build 指定为构建镜像上下文路径 ```yml services: app: build: context: ./dir dockerfile: Dockerfile-alternate args: buildno: 1 # 简写形式 build: ./dir ``` ##### ports 指定容器端口映射 ```yml services: web: ports: - "80:80" # 主机端口:容器端口 - "443:443" - "3000-3005:3000-3005" # 端口范围 - "9090-9091:8080-8081" ``` ##### volumes 主机目录挂载 ```yml services: web: volumes: - /var/lib/mysql # 匿名卷 - ./data:/var/lib/mysql # 绑定挂载 - db_data:/var/lib/mysql # 命名卷 - ./app:/app:ro # 只读挂载 volumes: db_data: # 声明命名卷 driver: local ``` ##### environment 环境变量设置 ```yml services: web: environment: - NODE_ENV=production - DATABASE_HOST=db - DEBUG=1 # 或者使用键值对形式 environment: NODE_ENV: production DATABASE_HOST: db ``` ##### env_file 从文件添加环境变量。可以是单个值或列表的多个值。 ```yml services: web: env_file: - ./common.env - ./apps/web.env # 或者单个文件 env_file: .env ``` #### 4、网络配置 ##### networks 配置容器连接的网络,引用顶级 networks 下的条目 。 ```yml services: web: networks: - frontend - backend database: networks: - backend networks: frontend: driver: bridge backend: driver: bridge driver_opts: com.docker.network.driver.mtu: 1450 ``` ##### 自定义网络配置 ```yml networks: mynet: driver: bridge ipam: config: - subnet: 172.20.0.0/16 internal: true # 内部网络 ``` #### 5、依赖和启动顺序 ##### depends_on 设置依赖关系。 - `docker-compose up` :以依赖性顺序启动服务。在以下示例中,先启动 `database` 和 `redis`,才会启动 web。 - `docker-compose up ` :自动包含 `SERVICE` 的依赖项。在以下示例中,`docker-compose up web` 还将创建并启动 `database` 和 `redis`。 - `docker-compose stop` :按依赖关系顺序停止服务。在以下示例中,`web` 在 `database` 和 `redis` 之前停止。 ```yml services: web: depends_on: - database - redis database: image: postgres:13 redis: image: redis:alpine ``` ##### 健康检查控制启动顺序 ```yml services: web: depends_on: database: condition: service_healthy redis: condition: service_started database: image: postgres:13 healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 10s timeout: 5s retries: 5 ``` #### 6、资源配置 ##### 资源限制配置 ```yml services: web: deploy: resources: limits: cpus: '0.50' memory: 512M reservations: cpus: '0.25' memory: 128M ``` ##### 简写形式(非 swarm 模式) ```yml services: web: mem_limit: 512m mem_reservation: 128m cpus: 0.5 cpu_shares: 73 ``` #### 7、重启策略 ```yml services: web: restart: always # 可选值: # "no" - 不自动重启 # "always" - 总是重启 # "on-failure" - 失败时重启 # "unless-stopped" - 除非手动停止,否则重启 ``` #### 8、健康检查 ```yml services: web: healthcheck: test: ["CMD", "curl", "-f", "http://localhost"] interval: 30s timeout: 10s retries: 3 start_period: 40s ``` #### 9、常用命令 ```bash # 启动服务 docker-compose up -d # 停止服务 docker-compose down # 查看服务状态 docker-compose ps # 查看日志 docker-compose logs -f # 构建服务 docker-compose build # 执行命令 docker-compose exec web python manage.py migrate ``` ## 七、其他内容 更多详细文档请参考官方:[Get started | Docker Docs](https://docs.docker.com/get-started/) Loading... Docker 是一个开源的**应用容器引擎**,基于 Go 语言开发。Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。 文档部分内容来自[Docker 教程 | 菜鸟教程](https://www.runoob.com/docker/docker-tutorial.html) ## 一、C/S架构 Docker 采用**客户端-服务器(C/S)架构**。核心组件是 **Docker 客户端** 和 **Docker 守护进程**。守护进程负责繁重的工作,如构建、运行和分发容器。客户端和守护进程可以运行在同一个系统上,也可以让客户端连接远程的守护进程。 ##### 1、架构图  #### 2、Docker 客户端 **角色**:用户与 Docker 交互的主要方式。 **功能**:当你使用 `docker run`、`docker build` 等命令时,客户端会将这些命令通过 **Docker API** 发送给 **Docker 守护进程**。 **特点**:一个客户端可以与多个守护进程通信。 #### 3、Docker 守护进程 **角色**:Docker 架构的“大脑”,是一个在后台运行的长寿命程序(通常在主机上以 `dockerd` 进程形式存在)。 **功能**: - 监听 Docker API 请求。 - 管理 Docker 的核心对象:**镜像**、**容器**、**网络**、**数据卷**。 - 与其他守护进程通信以管理 Docker 服务(在 Swarm 模式下)。 #### 4、Docker 核心对象(由守护进程管理) **镜像**:一个**只读模板**,带有创建 Docker 容器的指令。它类似于面向对象编程中的“类”。镜像通常基于其他镜像构建,并添加额外的定制层。例如,你可能会有一个基于 `ubuntu` 镜像的镜像,但安装了 Nginx 和你的应用程序代码。 **容器**:镜像的一个**可运行实例**。你可以使用 Docker API 或 CLI 创建、启动、停止、移动或删除容器。容器与镜像的关系,就像面向对象中“对象”与“类”的关系。容器是轻量级的,因为它默认只包含运行应用程序所需的进程和资源。 **网络**:Docker 提供了强大的网络功能,允许容器之间、容器与外部世界进行通信。可以创建自定义网络,将容器连接到特定网络中以实现隔离或互通。常见的网络驱动有 `bridge`(默认)、`host`、`overlay`(用于 Swarm 集群)等。 **数据卷**:用于持久化容器产生的数据以及容器间共享数据的机制。容器本身是临时的,当容器被删除,其内部的文件系统也会被销毁。数据卷将容器内的特定路径**映射**到主机上的一个目录,从而实现数据的持久化存储。 #### 5、Docker 镜像仓库 **角色**:存储和分发 Docker 镜像的服务。 **功能**: - **拉取镜像**:当您执行 `docker pull ubuntu` 时,Docker 客户端会指示守护进程从配置的镜像仓库(默认为 Docker Hub)拉取 `ubuntu` 镜像。 - **推送镜像**:当你构建了自己的镜像后,可以使用 `docker push` 命令将其推送到镜像仓库(公共或私有)以供他人使用。 **类型**: - **公共仓库**:如 **Docker Hub**,是默认的公共仓库,包含了大量官方和个人发布的镜像。 - **私有仓库**:如 Harbor、Nexus Repository,可以在公司内网搭建,用于存储私有镜像,保证代码安全和交付速度。 ## 二、安装Docker #### 1、脚本安装 使用Linux系统进行安装,测试系统版本为Ubuntu22.04 ```bash # 下载并执行Docker官方安装脚本 curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh ``` 安装成功后如图  #### 2、启动服务 ```bash # 启动Docker服务 sudo systemctl enable docker sudo systemctl start docker ``` #### 3、卸载Docker ```bash # 删除安装包 sudo apt-get purge docker-ce # 删除镜像、容器、配置文件等内容 sudo rm -rf /var/lib/docker ``` ## 三、使用Docker #### 1、HelloWorld Docker 允许你在容器内运行应用程序, 使用 `docker run` 命令来在容器内运行一个应用程序。 ```bash docker run ubuntu:22.04 /bin/echo "Hello world" ``` - `docker`:Docker 的二进制执行文件 - `run`:与前面的 docker 组合来运行一个容器 - ubuntu:22.04`:指定要运行的镜像,Docker 首先从本地主机上查找镜像是否存在,如果不存在,Docker 就会从镜像仓库 Docker Hub 下载公共镜像 - `/bin/echo "Hello world"`:在启动的容器里执行的命令  #### 2、交互式容器 通过 docker 的两个参数 `-i` `-t`,让 docker 运行的容器实现"对话"的能力 ```bash docker run -i -t ubuntu:22.04 /bin/bash ``` - `-t`:在新容器内指定一个伪终端或终端 - `-i`:允许你对容器内的标准输入 (STDIN) 进行交互  注意第二行 `root@0d11ad791a32:/#` ,此时我们已进入一个 ubuntu22.04 系统的容器 可以尝试在容器中运行命令 `cat /proc/version`和`ls`分别查看当前系统的版本信息和当前目录下的文件列表  可以通过运行 `exit` 命令或者使用 `CTRL+D` 来退出容器  #### 3、进程式容器 ##### 启动容器 使用命令`-d`参数创建一个以后台进程方式运行的容器,会返回输出容器的ID ```bash docker run -d ubuntu:22.04 /bin/sh -c "while true; do echo hello world; sleep 100; done" ```  ##### 容器列表 可以通过`docker ps`查看已经创建的容器状态,可以添加`-a`参数查看所有的容器  * `CONTAINER ID`:容器 ID * `IMAGE`:使用的镜像 * `COMMAND`:启动容器时运行的命令 * `CREATED`:容器的创建时间 * `STATUS`:容器状态,容器的状态有7种 - `created`:已创建 - `restarting`:重启中 - `running/Up` :运行中 - `removing`:迁移中 - `paused`:暂停 - `exited`:停止 - `dead`:死亡 * `PORTS`:容器的端口信息和使用的连接类型(tcp\udp) * `NAMES`:自动分配的容器名称 ##### 容器日志 可以通过`docker logs`查看容器内的标准输出,参数可以跟`ID/NAME`  ##### 停止容器 可以通过`docker stop`来停止正在运行中的容器,参数可以跟`ID/NAME`  #### 4、常用命令 | **命令** | **功能** | **示例** | | :-------------------- | :---------------------------------------------- | :----------------------------------------- | | `docker run` | 启动一个新的容器并运行命令 | `docker run -d ubuntu` | | `docker ps` | 列出当前正在运行的容器 | `docker ps` | | `docker ps -a` | 列出所有容器(包括已停止的容器) | `docker ps -a` | | `docker build` | 使用 Dockerfile 构建镜像 | `docker build -t my-image .` | | `docker images` | 列出本地存储的所有镜像 | `docker images` | | `docker pull` | 从 Docker 仓库拉取镜像 | `docker pull ubuntu` | | `docker push` | 将镜像推送到 Docker 仓库 | `docker push my-image` | | `docker exec` | 在运行的容器中执行命令 | `docker exec -it container_name bash` | | `docker stop` | 停止一个或多个容器 | `docker stop container_name` | | `docker start` | 启动已停止的容器 | `docker start container_name` | | `docker restart` | 重启一个容器 | `docker restart container_name` | | `docker rm` | 删除一个或多个容器 | `docker rm container_name` | | `docker rmi` | 删除一个或多个镜像 | `docker rmi my-image` | | `docker logs` | 查看容器的日志 | `docker logs container_name` | | `docker inspect` | 获取容器或镜像的详细信息 | `docker inspect container_name` | | `docker exec -it` | 进入容器的交互式终端 | `docker exec -it container_name /bin/bash` | | `docker network ls` | 列出所有 Docker 网络 | `docker network ls` | | `docker volume ls` | 列出所有 Docker 卷 | `docker volume ls` | | `docker-compose up` | 启动多容器应用(从`docker-compose.yml` 文件) | `docker-compose up` | | `docker-compose down` | 停止并删除由`docker-compose` 启动的容器、网络等 | `docker-compose down` | | `docker info` | 显示 Docker 系统的详细信息 | `docker info` | | `docker version` | 显示 Docker 客户端和守护进程的版本信息 | `docker version` | | `docker stats` | 显示容器的实时资源使用情况 | `docker stats` | | `docker login` | 登录 Docker 仓库 | `docker login` | | `docker logout` | 登出 Docker 仓库 | `docker logout` | **常用选项说明** - **`-d`**:后台运行容器,例如 `docker run -d ubuntu` - **`-it`**:以交互式终端运行容器,例如 `docker exec -it container_name bash` - **`-t`**:为镜像指定标签,例如 `docker build -t my-image` #### 5、容器使用 ##### 查看所有容器 ```bash docker ps -a ```  ##### 启动已停止的容器 ```bash docker start <ID/NAME> docker restart <ID/NAME> ```  ##### 进入容器 在使用 `-d` 参数时启动容器时,容器会运行在后台,这时如果要进入容器,可以通过以下命令进入: - `docker attach`:允许你与容器的标准输入(stdin)、输出(stdout)和标准错误(stderr)进行交互 - `docker exec`:推荐使用 `docker exec` 命令,因为此命令会退出容器终端,但不会导致容器的停止 `docker attach`  **注意**:如果从这个容器退出,会导致容器的停止。 `docker exec` 该命令需要至少 2 个参数 ```bash docker exec -it <ID/NAME> <命令> ```  ##### 导出容器 默认的导出目录为当前命令运行的目录 ```bash docker export <ID/NAME> > filename.tar ```  ##### 导入容器快照 ```bash docker import <path> <name/image:tag> ```  ##### 删除容器 删除单个容器 ```bash docker rm <ID/NAME> ``` **注意**:要删除的容器必须为已停止的容器  删除所有已停止容器 ```bash docker container prune ``` ##### 端口映射 在docker容器中运行一个 Python Flask 应用来运行一个web应用 ```bash # 拉取镜像 docker pull nginx # 创建目录 mkdir -p /www/wwwroot/test # 运行容器 docker run -d -p 80:80 -v /www/wwwroot/test:/usr/share/nginx/html nginx ``` - `-d`:让容器在后台运行 - `-p <主机>:<容器>`:将容器内部使用的网络端口映射到主机上 - `-v <主机>:<容器>`:将主机的目录挂载到容器中  将测试`index.html`文件上传到`/www/wwwroot/test` ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Hello world</title> </head> <body> <h1> 你好,世界 </h1> </body> </html> ``` 访问当前主机IP地址,本地测试可以访问`localhost`或者`127.0.0.1`  ##### 查看容器端口 ```html docker port <ID/NAME> ```  同样的可以通过`docker logs -f <ID/NAME>`来查看流式标准输出  #### 6、镜像使用 ##### 镜像列表 ```bash docker images ```  - `IMAGE`:表示镜像的名称 - `ID`:镜像ID - `DISK USAGE`:镜像占用磁盘大小 - `CONTENT SIZE`:镜像内容大小 - `EXTRA`:镜像使用状态 ##### 拉取镜像 ```bash docker pull <image:tag> ```  ##### 搜索镜像 可以从 Docker Hub 网站来搜索镜像,Docker Hub 网址为: https://hub.docker.com/ ```bash docker search <image> ```  * `NAME`:镜像仓库源的名称 * `DESCRIPTION`:镜像的描述 * `OFFICIAL`:是否 docker 官方发布 * `stars`:类似 Github 里面的 star,表示点赞、喜欢的意思 ##### 删除本地镜像 ```bash docker rmi <ID/NAME> ```  ##### 更新(提交)镜像 通过镜像创建的容器后,在容器内进行操作后想要保存成镜像就需要提交镜像更新 ```bash docker commit -m="描述" -a="作者" <容器ID> <image:tag> ```  ##### 构建镜像 从零构建镜像需要使用到`Dockerfile`文件,其中包含一组指令来告诉 Docker 如何构建我们的镜像 在当前目录下创建一个`Dockerfile` ```dockerfile FROM centos:6.7 MAINTAINER Fisher "fisher@sudops.com" RUN /bin/echo 'root:123456' |chpasswd RUN useradd doooog RUN /bin/echo 'doooog:123456' |chpasswd RUN /bin/echo -e "LANG=\"en_US.UTF-8\"" >/etc/default/local EXPOSE 22 EXPOSE 80 CMD /usr/sbin/sshd -D ``` 使用`docker build`构建镜像 ```bash docker build -t doooog/centos:6.7 . ``` - `-t` :指定要创建的目标镜像名 - `.` :Dockerfile 文件所在目录,可以指定Dockerfile 的绝对路径  通过`docker images`查看镜像列表,并通过`docker run -t -i doooog/centos:6.7 /bin/bash`创建容器  ##### 推送镜像 用户登录后,可以通过 `docker push` 命令将自己的镜像推送到 Docker Hub。 ```bash docker push <image:tag> ``` ## 四、容器互联 端口映射并不是唯一把 docker 连接到另一个容器的方法。 docker 有一个连接系统允许将多个容器连接在一起,共享连接信息,docker 连接会创建一个父子关系,其中父容器可以看到子容器的信息。 #### 1、新建网络 ```bash docker network create -d bridge <name> ``` * `-d`:参数指定 Docker 网络类型,有 `bridge`、`overlay`。 可以通过`docker network ls`来查看已经建立的网络  #### 2、连接容器 ```bash # 创建容器1 docker run -itd --name test1 --network test-net ubuntu:22.04 /bin/bash # 创建容器2 docker run -itd --name test2 --network test-net ubuntu:22.04 /bin/bash # 进入容器test1 docker exec -it <ID> /bin/bash # 更新仓库 apt-get update # 安装ping工具 apt install iputils-ping # ping容器test2 ping test2 ``` * `--name`:对容器自定义命名 * `--network`:将容器连接到网络   #### 3、配置DNS ##### 设置Docker全局DNS 修改宿主机的 `/etc/docker/daemon.json` 文件中增加以下内容来设置全部容器的DNS,启动容器的 DNS 会自动配置为 `114.114.114.114` 和 `8.8.8.8` ```bash { "dns" : [ "114.114.114.114", "8.8.8.8" ] } ``` **注意**:需要将docker服务重启才可以生效`sudo systemctl restart docker` ##### 容器指定DNS ```bash docker run -it --rm -h <主机名> --dns=<DNS> --dns-search=<DOMAIN> <image:tag> ``` * `--rm`:容器退出时自动清理容器内部的文件系统 * `-h HOSTNAME` / `--hostname=HOSTNAME`:设定容器的主机名,它会被写到容器内的 `/etc/hostname` 和 `/etc/hosts` * `--dns=IP_ADDRESS`:添加 DNS 服务器到容器的 `/etc/resolv.conf` 中,让容器用这个服务器来解析所有不在 `/etc/hosts` 中的主机名 * `--dns-search=DOMAIN`: 设定容器的搜索域,当设定搜索域为 `.example.com` 时,在搜索一个名为 `host` 的主机时,DNS 不仅搜索 `host`,还会搜索 `host.example.com` 如果在容器启动时没有指定 `--dns` 和 `--dns-search`,Docker 会默认用宿主主机上的 `/etc/resolv.conf` 来配置容器的 DNS。 ## 五、Dockerfile `Dockerfile` 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明,通过定义一系列命令和参数,Dockerfile 指导 Docker 构建一个自定义的镜像。 #### 1、常用命令 | Dockerfile 指令 | 说明 | | :-------------- | :------------------------------------------------------------------- | | `FROM` | 指定基础镜像,用于后续的指令构建。 | | `MAINTAINER` | 指定Dockerfile的作者/维护者。(已弃用,推荐使用LABEL指令) | | `LABEL` | 添加镜像的元数据,使用键值对的形式。 | | `RUN` | 在构建过程中在镜像中执行命令。 | | `CMD` | 指定容器创建时的默认命令。(可以被覆盖) | | `ENTRYPOINT` | 设置容器创建时的主要命令。(不可被覆盖) | | `EXPOSE` | 声明容器运行时监听的特定网络端口。 | | `ENV` | 在容器内部设置环境变量。 | | `ADD` | 将文件、目录或远程URL复制到镜像中。 | | `COPY` | 将文件或目录复制到镜像中。 | | `VOLUME` | 为容器创建挂载点或声明卷。 | | `WORKDIR` | 设置后续指令的工作目录。 | | `USER` | 指定后续指令的用户上下文。 | | `ARG` | 定义在构建过程中传递给构建器的变量,可使用 "docker build" 命令设置。 | | `ONBUILD` | 当该镜像被用作另一个构建过程的基础时,添加触发器。 | | `STOPSIGNAL` | 设置发送给容器以退出的系统调用信号。 | | `HEALTHCHECK` | 定义周期性检查容器健康状态的命令。 | | `SHELL` | 覆盖Docker中默认的shell,用于RUN、CMD和ENTRYPOINT指令。 | #### 2、FROM 定制的镜像都是基于 FROM 的镜像,后面跟着基于镜像的名称 ```dockerfile FROM <image> ``` #### 3、RUN 用于执行后面跟着的命令行命令 ##### Shell 格式 ```dockerfile RUN <命令行命令> # <命令行命令> 等同于,在终端操作的 shell 命令。 ``` ##### Exec 格式 ```dockerfile RUN ["可执行文件", "参数1", "参数2"] # 例如: # RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php dev offline ``` ##### 注意 Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。例如: ```dockerfile FROM centos RUN yum -y install wget RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" RUN tar -xvf redis.tar.gz ``` 以上执行会创建 `3` 层镜像。可简化为以下格式: ```dockerfile FROM centos RUN yum -y install wget \ && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \ && tar -xvf redis.tar.gz ``` 如上,以 `&&` 符号连接命令,这样执行后,只会创建 `1` 层镜像。 #### 4、COPY 从宿主机复制文件/目录到镜像中 ##### 语法 ```dockerfile COPY [--chown=<user>:<group>] <源路径1>... <目标路径> COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"] ``` * `[--chown=<user>:<group>]`:可选参数,用户改变复制到容器内文件的拥有者和属组。 * `<源路径>`:源文件或者源目录,这里可以是通配符表达式,其通配符规则要满足 Go 的 filepath.Match 规则。 ##### 示例 ```dockerfile COPY app.py /app/ COPY --chown=node:node . /app ``` #### 5、ADD 类似 COPY,但支持自动解压和 URL 下载 ##### 语法 ```dockerfile ADD [--chown=<user>:<group>] <源路径1>... <目标路径> ADD [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"] ``` ##### 示例 ```dockerfile ADD https://example.com/file.tar.gz /tmp/ ADD data.tar.gz /app/data/ ``` #### 6、CMD 类似于 RUN 指令,用于运行程序,但二者运行的时间点不同: - `CMD` 在docker run 时运行。 - `RUN` 是在 docker build。 为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。 ##### 语法 ```dockerfile CMD command param1 param2 CMD ["executable","param1","param2"] ``` ##### 示例 ```dockerfile CMD nginx -g 'daemon off;' CMD ["python", "app.py"] ``` #### 7、ENTRYPOINT 类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。 ##### 语法 ```dockerfile ENTRYPOINT command param1 param2 ENTRYPOINT ["executable", "param1", "param2"] ``` ##### 示例 ```dockerfile ENTRYPOINT ["nginx", "-c"] # 定参 CMD ["/etc/nginx/nginx.conf"] # 变参 ``` #### 8、ENV 设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。 ##### 语法 ```dockerfile ENV <key>=<value> ... ``` ##### 示例 ```dockerfile ENV NODE_ENV=production ENV APP_HOME=/app PATH=/usr/local/bin:$PATH ``` #### 9、ARG 构建参数,与 ENV 作用一致。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。 构建命令 docker build 中可以用 `--build-arg <参数名>=<值>` 来覆盖。 ##### 语法 ```dockerfile ARG <name>[=<default value>] ``` ##### 示例 ```dockerfile ARG VERSION=latest FROM ubuntu:${VERSION} ``` #### 10、WORKDIR 指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会建立目录。 ##### 语法 ```dockerfile WORKDIR /path/to/workdir ``` ##### 示例 ```dockerfile WORKDIR /app RUN npm install ``` #### 11、USER 用于指定执行后续命令的用户和用户组,这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)。 ##### 语法 ```dockerfile USER <用户名>[:<用户组>] ``` ##### 示例 ```dockerfile USER nobody USER 1000:1000 ``` #### 12、EXPOSE 声明容器运行时监听的端口,帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射,在运行时使用随机端口映射时,也就是 `docker run -P` 时,会自动随机映射 EXPOSE 的端口。 ##### 语法 ```dockerfile EXPOSE <port> [<port>/<protocol>...] ``` ##### 示例 ```dockerfile EXPOSE 80 EXPOSE 443/tcp 8080/udp ``` #### 13、VOLUME 定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。可以避免重要的数据,因容器重启而丢失,这是非常致命的。 在启动容器 docker run 的时候,我们可以通过 `-v` 参数修改挂载点。 ##### 语法 ```dockerfile VOLUME ["<路径1>", "<路径2>"...] VOLUME <路径> ``` ##### 示例 ```dockerfile VOLUME ["/data", "/logs"] VOLUME /var/lib/mysql ``` #### 14、LABEL LABEL 指令用来给镜像添加一些元数据(metadata),以键值对的形式 ##### 语法 ```dockerfile LABEL <key>=<value> <key>=<value> ... ``` ##### 示例 ```dockerfile LABEL version="1.0" LABEL maintainer="dev@example.com" description="Web app" ``` #### 15、HEALTHCHECK 用于指定某个程序或者指令来监控 docker 容器服务的运行状态。 ##### 语法 ```dockerfile HEALTHCHECK [选项] CMD <命令> # 设置检查容器健康状况的命令 HEALTHCHECK NONE # 如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令 HEALTHCHECK [选项] CMD <命令> # 这边 CMD 后面跟随的命令使用,可以参考 CMD 的用法。 ``` ##### 示例 ```dockerfile HEALTHCHECK --interval=30s --timeout=3s \ CMD curl -f http://localhost/ || exit 1 ``` #### 16、STOPSIGNAL 设置发送给容器以退出的系统调用信号 ##### 语法 ```dockerfile STOPSIGNAL signal ``` ##### 示例 ```dockerfile STOPSIGNAL SIGTERM ``` #### 17、SHELL 覆盖Docker中默认的shell,用于RUN、CMD和ENTRYPOINT指令 ##### 语法 ```dockerfile SHELL ["executable", "parameters"] ``` ##### 示例 ```dockerfile SHELL ["/bin/bash", "-c"] ``` #### 18、ONBUILD 用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜像的过程中不会执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这时执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令。为`子镜像`设置触发指令。 ##### 语法 ```dockerfile ONBUILD <INSTRUCTION> ``` ##### 示例 ```dockerfile ONBUILD COPY . /app ONBUILD RUN make build ``` #### 19、AS 为构建阶段的命令取别名 ##### 示例 ```dockerfile FROM node:14 AS build-stage FROM nginx:alpine AS production-stage COPY --from=build-stage /app/dist /usr/share/nginx/html ``` ## 六、Docker Compose Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,可以使用 `YML` 文件来配置应用程序需要的所有服务。 #### 1、安装 ```bash # 下载可执行文件 sudo curl -L "https://github.com/docker/compose/releases/download/v5.0.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose # 赋予可执行权限 sudo chmod +x /usr/local/bin/docker-compose # 创建软链接 sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose # 测试版本 docker-compose version ``` **注意**:安装其他版本仅需更改`v5.0.0`  #### 2、使用示例 ##### 创建测试目录 ```bash mkdir composetest cd composetest ``` ##### 创建`app.py` ```python import time import redis from flask import Flask app = Flask(__name__) cache = redis.Redis(host='redis', port=6379) def get_hit_count(): retries = 5 while True: try: return cache.incr('hits') except redis.exceptions.ConnectionError as exc: if retries == 0: raise exc retries -= 1 time.sleep(0.5) @app.route('/') def hello(): count = get_hit_count() return 'Hello World! I have been seen {} times.\n'.format(count) ``` ##### 创建`requirements.txt` python程序的依赖文件清单 ```python flask redis ``` ##### 创建`Dockerfile` ```dockerfile FROM python:3.7-alpine WORKDIR /code ENV FLASK_APP app.py ENV FLASK_RUN_HOST 0.0.0.0 RUN apk add --no-cache gcc musl-dev linux-headers COPY requirements.txt requirements.txt RUN pip install -r requirements.txt COPY . . CMD ["flask", "run"] ``` - `FROM python:3.7-alpine`: 从 Python 3.7 映像开始构建镜像。 - `WORKDIR /code`: 将工作目录设置为 /code。 - ``` ENV FLASK_APP app.py ENV FLASK_RUN_HOST 0.0.0.0 ``` 设置 flask 命令使用的环境变量。 - `RUN apk add --no-cache gcc musl-dev linux-headers`: 安装 gcc,以便诸如 MarkupSafe 和 SQLAlchemy 之类的 Python 包可以编译加速。 - ``` COPY requirements.txt requirements.txt RUN pip install -r requirements.txt ``` 复制 requirements.txt 并安装 Python 依赖项。 - `COPY . .`: 将 . 项目中的当前目录复制到 . 镜像中的工作目录。 - `CMD ["flask", "run"]`: 容器提供默认的执行命令为:flask run。 ##### 创建`docker-compose.yml` ```yml # yaml 配置 version: '3' services: web: build: . ports: - "5000:5000" redis: image: "redis:alpine" ``` 该 Compose 文件定义了两个服务:web 和 redis。 - `web`:该 web 服务使用从 Dockerfile 当前目录中构建的镜像。然后,它将容器和主机绑定到暴露的端口 5000。此示例服务使用 Flask Web 服务器的默认端口 5000 。 - `redis`:该 redis 服务使用 Docker Hub 的公共 Redis 映像。 ##### 构建镜像与容器 在测试目录中,执行以下命令来启动应用程序: ```bash docker-compose up ``` 在后台执行该服务可以加上 **-d** 参数: ```bash docker-compose up -d ```   访问`ip:5000`本地测试环境可以访问`localhost:5000`或`127.0.0.1:5000`  #### 3、服务定义指令 ##### image 指定容器运行的镜像。以下格式都可以: ```yml image: redis image: ubuntu:14.04 image: tutum/influxdb image: example-registry.com:4000/postgresql image: a4bc65fd # 镜像id ``` 示例 ```yml services: web: image: nginx:1.20 image: redis:alpine ``` ##### build 指定为构建镜像上下文路径 ```yml services: app: build: context: ./dir dockerfile: Dockerfile-alternate args: buildno: 1 # 简写形式 build: ./dir ``` ##### ports 指定容器端口映射 ```yml services: web: ports: - "80:80" # 主机端口:容器端口 - "443:443" - "3000-3005:3000-3005" # 端口范围 - "9090-9091:8080-8081" ``` ##### volumes 主机目录挂载 ```yml services: web: volumes: - /var/lib/mysql # 匿名卷 - ./data:/var/lib/mysql # 绑定挂载 - db_data:/var/lib/mysql # 命名卷 - ./app:/app:ro # 只读挂载 volumes: db_data: # 声明命名卷 driver: local ``` ##### environment 环境变量设置 ```yml services: web: environment: - NODE_ENV=production - DATABASE_HOST=db - DEBUG=1 # 或者使用键值对形式 environment: NODE_ENV: production DATABASE_HOST: db ``` ##### env_file 从文件添加环境变量。可以是单个值或列表的多个值。 ```yml services: web: env_file: - ./common.env - ./apps/web.env # 或者单个文件 env_file: .env ``` #### 4、网络配置 ##### networks 配置容器连接的网络,引用顶级 networks 下的条目 。 ```yml services: web: networks: - frontend - backend database: networks: - backend networks: frontend: driver: bridge backend: driver: bridge driver_opts: com.docker.network.driver.mtu: 1450 ``` ##### 自定义网络配置 ```yml networks: mynet: driver: bridge ipam: config: - subnet: 172.20.0.0/16 internal: true # 内部网络 ``` #### 5、依赖和启动顺序 ##### depends_on 设置依赖关系。 - `docker-compose up` :以依赖性顺序启动服务。在以下示例中,先启动 `database` 和 `redis`,才会启动 web。 - `docker-compose up <SERVICE>` :自动包含 `SERVICE` 的依赖项。在以下示例中,`docker-compose up web` 还将创建并启动 `database` 和 `redis`。 - `docker-compose stop` :按依赖关系顺序停止服务。在以下示例中,`web` 在 `database` 和 `redis` 之前停止。 ```yml services: web: depends_on: - database - redis database: image: postgres:13 redis: image: redis:alpine ``` ##### 健康检查控制启动顺序 ```yml services: web: depends_on: database: condition: service_healthy redis: condition: service_started database: image: postgres:13 healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 10s timeout: 5s retries: 5 ``` #### 6、资源配置 ##### 资源限制配置 ```yml services: web: deploy: resources: limits: cpus: '0.50' memory: 512M reservations: cpus: '0.25' memory: 128M ``` ##### 简写形式(非 swarm 模式) ```yml services: web: mem_limit: 512m mem_reservation: 128m cpus: 0.5 cpu_shares: 73 ``` #### 7、重启策略 ```yml services: web: restart: always # 可选值: # "no" - 不自动重启 # "always" - 总是重启 # "on-failure" - 失败时重启 # "unless-stopped" - 除非手动停止,否则重启 ``` #### 8、健康检查 ```yml services: web: healthcheck: test: ["CMD", "curl", "-f", "http://localhost"] interval: 30s timeout: 10s retries: 3 start_period: 40s ``` #### 9、常用命令 ```bash # 启动服务 docker-compose up -d # 停止服务 docker-compose down # 查看服务状态 docker-compose ps # 查看日志 docker-compose logs -f # 构建服务 docker-compose build # 执行命令 docker-compose exec web python manage.py migrate ``` ## 七、其他内容 更多详细文档请参考官方:[Get started | Docker Docs](https://docs.docker.com/get-started/) 最后修改:2025 年 12 月 16 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 👆请简单粗暴地爱我。