Docker学习笔记(高阶篇)一

一、Docker Dockerfile


Docker Dockerfile是一个文本文件,包含了一系列的指令和参数,用于自动化构建Docker镜像。每条指令都构建镜像的一层,每一层都代表了镜像构建过程中的一个步骤。该层包含了该指令执行后的所有更改,这些层最终会叠加起来形成最终的镜像。

镜像层的工作原理

假设我们有一个非常基础的Dockerfile:

FROM ubuntu:18.04
RUN apt-get update && apt-get install -y nginx
COPY . /var/www/html

这个Dockerfile包含了三条指令,每条指令对应镜像的一层:

  • FROM ubuntu:18.04:这是基础镜像层,所有后续的操作都基于这个Ubuntu 18.04的镜像。
  • RUN apt-get update && apt-get install -y nginx:这一条指令创建了第二层。这层在Ubuntu 18.04的基础上,更新了软件包列表并安装了nginx。这一层只包含了由于安装nginx而产生的改变。
  • COPY . /var/www/html:这一条指令创建了第三层。它把宿主机当前目录下的文件复制到了镜像的/var/www/html目录中。这层包含了由于复制文件操作产生的所有改变。

层的重用和缓存

当Dockerfile被重新构建时,如果FROM指令指定的基础镜像没有变化,且RUN指令执行的安装命令没有变化,那么Docker会使用缓存的镜像层,而不是重新创建。这大大加快了构建过程。

但是如果你修改了COPY指令复制的文件内容(哪怕是一个小小的改变),Docker需要重新执行这条指令以及所有后续的指令,因为这会影响到/var/www/html目录的内容,从而影响到这一层以及所有基于这一层的后续层。

层的效率

Docker镜像的这种分层结构,使得镜像的分发非常高效。如果多个镜像都是基于相同的Ubuntu 18.04基础镜像,那么这个基础镜像只需要在一个节点上存储和缓存一次,不同的镜像只需存储它们自己特有的层。

二、Dockerfile常用指令


截止到发文当天,Dockerfile支持18个常用字的保留指令:

指令列表

1.FROM:指定基础镜像。所有Dockerfile都必须以FROM指令开始,指定一个已存在的镜像作为构建新镜像的基础:

FROM ubuntu:18.04

2.RUN:在镜像中运行命令。用于安装软件包或执行其它配置任务:

RUN apt-get update && apt-get install -y python3

3.CMD:提供容器默认执行的命令。Dockerfile中只能有一个CMD指令。如果定义了多个,只有最后一个会被执行:

CMD ["python3", "./app.py"]

4.COPY:将主机的文件或目录复制到镜像中。常用于复制源代码到镜像内:

COPY . /app

5.ADD:与COPY类似,但是它还支持远程URL和自动解压压缩文件的功能:

ADD https://example.com/big.tar.gz /var/www/html/

6.EXPOSE:声明容器运行时监听的端口:

EXPOSE 80

7.ENV:设置环境变量:

ENV MYSQL_ROOT_PASSWORD password
ENV MYSQL_DATABASE my_database
ENV MYSQL_USER my_user
ENV MYSQL_PASSWORD my_password

8.ENTRYPOINT:配置容器启动时运行的命令,与CMD配合使用,可以让容器以应用程序或服务的形式运行:

ENTRYPOINT ["python3"]
CMD ["app.py"]
官方配置参数说明 官方配置参数说明

当你的dockerfile文件编辑好后,切换到dockerfile文件所在目录下构建镜像:

docker build -t your-image-name:tag .

使用docker run -d命令来运行该镜像即可。

二、Docker Compose


Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。

使用Compose的步骤

  1. 编写Dockerfile:这是创建自定义Docker镜像的步骤,你会在这个文件中定义基础镜像、安装必要的软件包、配置环境、复制应用程序文件等步骤。这个步骤是为了创建一个能够满足你特定需求的镜像。
  2. 编写docker-compose.yml文件:在这个文件中,定义你的应用所需的服务、网络和卷。这包括使用哪些镜像(无论是自定义镜像还是直接从Docker Hub拉取的镜像)、如何配置容器之间的网络、容器需要挂载哪些卷等。
  3. 运行docker-compose up -d命令:这一步会根据你在docker-compose.yml文件中定义的配置启动和运行你的应用。-d参数表示在后台运行容器。
  4. 通过docker-compose down进行清理:用于停止并删除根据docker-compose.yml文件创建的所有容器,网络和默认创建的卷。

在Docker中,使用docker-compose up -d命令时并不一定需要有一个自己创建的Dockerfile文件。例如下面是一个基于nginx官方镜像启动一个简单web服务器的docker-compose.yml示例,这里并不需要Dockerfile

version: '3'
services:
  web:
    image: nginx:latest
    ports:
      - "80:80"
    volumes:
      - ./html:/usr/share/nginx/html

在这个示例中,image: nginx:latest指示Docker使用已有的最新的nginx官方镜像。因此只要你有这个docker-compose.yml文件,就可以使用docker-compose up -d命令来启动服务,无需自己编写Dockerfile

但是如果你想要构建一个自定义的镜像(例如,你有特定的环境配置或者应用程序需要包含在镜像中),那么你就需要自行创建一个Dockerfile来指定如何构建这个镜像,并在docker-compose.yml文件中使用build:指令指向包含Dockerfile的目录。

Docker Compose文件格式(docker-compose.yml

Compose 文件是一个YAML文件,其中定义了所有相关的服务设置。一个服务通常表示运行一个容器。服务可以包括应用的数据库、web服务、前端服务等。

Compose文件的结构大致如下:

version: '3'

services:
  db:
    image: postgres
    volumes:
      - db-data:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: exampledb
      POSTGRES_USER: exampleuser
      POSTGRES_PASSWORD: examplepass
  
  web:
    build: .
    command: python app.py
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    depends_on:
      - db

volumes:
  db-data:

在这个例子中:

  • db服务使用了postgres镜像,并定义了一个卷db-data来持久化数据库数据。
  • web服务通过build: .指令构建当前目录下的Dockerfile,并且映射了端口8000到容器的端口8000。
  • depends_on指令确保在启动web服务之前数据库db服务已经在运行。

这样定义了服务后,使用docker-compose up -d命令就可以一起启动这两个服务。它们会在同一个网络中创建,web服务能够通过数据库服务名称db来访问数据库服务。

docker compose版本查询 docker compose版本查询
docker-compose 指令列表

三、总结


  • Dockerfile:它的作用是定义如何从一个基础镜像开始,通过一系列步骤构建出一个新的镜像。这些步骤可能包括安装软件包、设置环境变量、复制应用程序代码到镜像中等。Dockerfile关注的是镜像的创建,是构建过程的一张清单说明。
  • docker-compose.yml:这个文件则用于定义和运行基于Docker的应用。它允许你用YAML格式配置应用的服务、网络和卷,这些服务可以基于你通过Dockerfile构建的镜像,也可以是直接从Docker Hub或其他Docker镜像仓库拉取的现成镜像。docker-compose.yml关注的是如何将一个或多个镜像组织成完整的应用,处理服务之间的关系、网络连接和数据存储。

所以Dockerfile 是关于构建镜像的,“怎样做”这个镜像;而 docker-compose.yml 是关于部署和管理这些镜像作为服务的,即如何把这些镜像“运作起来”,使它们共同作为一个整体服务运行。

docker Compose 虽然是官方提供的容器编排工具,但是实际生产环境是不用的,因为其局限性很大,这只适合单机多容器部署进行本地开发环境、测试环境以及小型的生产部署。但并不直接支持跨多个主机或管理一个容器集群。对于生产环境中的容器编排和集群管理,更倾向于使用像Kubernetes这样的系统。因为Kubernetes提供了更强大的功能,能够处理跨主机的容器编排、自动扩展、服务发现、负载均衡、自我修复等复杂功能,这些是Docker Compose所不具备的。