Docker 简明教程
Docker - Dockerfile
Dockerfile 是一种文本文档,你可以在其中写下要创建镜像的所有指令。该文件中的第一个条目指定基本镜像,基本镜像是一个预制的镜像,其中包含你的应用程序所需的所有依赖项。然后,你可以向 Dockerfile 发送命令,以安装附加软件、复制文件或运行脚本。其结果是一个 Docker 镜像:一个自给自足的可执行文件,其中包含运行应用程序所需的所有信息。
A Dockerfile is a text document in which you can lay down all the instructions that you want for an image to be created. The first entry in the file specifies the base image, which is a pre-made image containing all the dependencies you need for your application. Then, there are commands you can send to the Dockerfile to install additional software, copy files, or run scripts. The result is a Docker image: a self-sufficient, executable file with all the information needed to run an application.
Dockerfile 是一种颇具吸引力的用于创建和部署应用程序的方式。它们有助于以一种更加轻松的方式和可重复的方式创建环境。Dockerfile 还能自动执行部署流程。
Dockerfiles are a compelling way to create and deploy applications. They help in creating an environment consistently reproducibly, and in an easier way. Dockerfiles also automate the deployment process.
Dockerfile 用于创建根据具体需求单独准备的新自定义镜像。例如,Docker 镜像可以具有特定版本的 Web 服务器,或者例如数据库服务器。
A Dockerfile is used to create new custom images prepared individually according to specific needs. For instance, a Docker image can have a particular version of a web server or, for example, a database server.
Important Instructions used in Dockerfile
Dockerfile 是一种文本文档,其中包含所有用于构建 Docker 镜像的不同步骤和说明。Dockerfile 中描述的主要元素包括基本镜像、所需依赖项以及在容器中执行应用程序部署的命令。
A Dockerfile is a text document that includes all the different steps and instructions on how to build a Docker image. The main elements described in the Dockerfile are the base image, required dependencies, and commands to execute application deployment within a container.
Dockerfile 的基本指令如下所示 −
The essential instructions of a Dockerfile are illustrated below −
FROM
此指令设置用于在新镜像上构建的新镜像的基础镜像。它通常是 Dockerfile 中的第一个指令。
This instruction sets the base image on which the new image is going to be built upon. It is usually the first instruction in a Dockerfile.
FROM ubuntu:22
RUN
这将是一条指令,它将用于在构建时运行容器内的命令。它通常可以被用于安装应用程序、更新程序库或执行常规设置。
This will be an instruction that will be executed for running the commands inside the container while building. It typically can be utilized to install an application, update libraries, or do general setup.
RUN apt-get update && apt-get install -y python3
COPY
此指令将文件和目录从宿主机器复制到容器镜像中。
This instruction copies files and directories from the host machine into the container image.
COPY ./app /app
ADD
它很像 COPY 但功能更加高级,例如自动解压存档并从 URL 中提取文件。
Like COPY but more advanced in features like it auto-decompresses archives and fetches files from URLs.
ADD https://example.com/file.tar.gz /app
WORKDIR
此指令设置工作目录,其中 Dockerfile 中的后继指令将被执行。
The instruction sets the working directory where the subsequent commands in a Dockerfile will be executed.
WORKDIR /app
ENV
此命令中的 ENV 指令定义容器内的环境变量。
The ENV instruction in this command defines environment variables within the container.
ENV FLASK_APP=main.py
EXPOSE
此选项定义要让 Docker 在运行时侦听声明网络端口。
This option defines to Docker that the container listens on the declared network ports at runtime.
EXPOSE 8000
CMD
定义执行容器的默认设置。Dockerfile 中只可以有一个 CMD 指令。如果列出了多个 CMD,那么只有最后一个 CMD 将生效。
Defines defaults for an executing container. There can only be one CMD instruction in a Dockerfile. If you list more than one CMD, then only the last CMD will take effect.
CMD ["python3", "main.py"]
ENTRYPOINT
一条指令,允许配置容器,以便将容器作为可执行文件运行。
This is an instruction that enables the configuration of a container to run the container as an executable.
ENTRYPOINT ["python3", "main.py"]
LABEL
此命令为镜像提供元信息,比如维护人员的详细信息、版本或说明。
This command provides meta-information for an image, like details of the maintainer, version, or description.
LABEL maintainer="johndoe@example.com"
ARG
此命令定义了一个变量,允许用户在构建时通过 docker build 命令上的“--build-arg”标志传递给构建器。
This command defines a variable that allows users to be passed to the builder at build time using the "--build-arg" flag on the docker build command.
ARG version=1
VOLUME
它只是创建一个挂载点并为其分配给定的名称,指出它将保存来自本机主机或其他容器的外置挂载卷。
It simply creates a mount point and assigns the given name to it, indicating that it will hold externally mounted volumes from the native host or other containers.
VOLUME /app/data
USER
此指令允许设置用户名(或 UID),还可以可选地设置在运行该镜像时和 Dockerfile 中后续的任何 RUN、CMD 和 ENTRYPOINT 指令时使用的组(或 GID)。
This instruction allows the setting of the username (or UID) and optionally the group (or GID) to be used when running that image and for any RUN, CMD, and ENTRYPOINT instructions that follow it in the Dockerfile.
USER johndoe
这些可能是在 Dockerfile 中使用最常见也是最重要的指令。然而,这些指令及其顺序当然会根据要容器化的特定应用程序而异。
These are probably the most common and vital instructions used in a Dockerfile. However, the instructions and their order would, of course, vary according to the specific application to be containerized.
Best Practices for Dockerfile
一份编写得当的 Dockerfile 对于所有高效且安全的容器化应用程序都至关重要。Dockerfile 是构建 Docker 镜像的蓝图,其中详细说明了顺畅运行应用程序所需的环境、依赖关系和配置。
A nicely put Dockerfile is central to all efficient and secure containerized applications. A Dockerfile is a blueprint for building Docker images and details the environment, dependencies, and configurations needed to operate your application smoothly.
通过最佳实践,你可以创建更精简、更快速且更可靠的 Docker 镜像,从而最终实现工作流的自动化,提高应用程序的效率。以下给出了一组 10 个基本的 Dockerfile 最佳实践−
Through best practices, you can create leaner, faster, and more reliable Docker images, which eventually automate workflows in development and increase efficiency in the application. Given below is a set of 10 fundamental Dockerfile best practices −
-
Use Official Base Images − Build on top of the official Docker Hub images. They tend to be minimal and well-maintained. Usually, they are optimized for security and size, laying a solid foundation for a custom image.
-
Use multi-stage builds to slash your final image size by dropping unwanted build tools and dependencies. This way, you partition the build and runtime environment to attain peak efficiencies.
-
Minimize the Number of Layers − As you learned earlier, each instruction in a Dockerfile creates a layer. Whenever possible, combine any commands related to one another in a single RUN instruction. This will help reduce the number of layers created for any build, making builds more cacheable.
-
Leverage Build Cache − Ensure that Dockerfile instructions that can change more frequently, such as COPY, are placed towards the end. This would enable building again more rapidly upon making changes at later stages.
-
Install Only Necessary Packages − Install only necessary packages and dependencies in your application to reduce the image size and possible vulnerabilities there.
-
Use '.dockerignore' − To exclude unnecessary files and directories from the build context, add a '.dockerignore' file. This will speed up builds and prevent sensitive information from being leaked into your image.
-
Use Non-Root User − Run containers with a non-root user to enhance security. It is always a good idea to give a specific user and group in Dockerfile another isolation layer.
-
Image Scanning − Scan your Docker images often for vulnerabilities. With technologies such as Trivy and Clair, there are several tools that you could use for this kind of scanning. Keep your base images and dependencies up to date at all times to minimize the potential risk.
-
Document your Dockerfile − Comment and explain your Dockerfile, you’ll thank yourself later. This helps others, even your future self, understand the build process.
-
Pin Versions − Pin versions for base images and dependencies, as this ensures reproducibility and avoids any unintended issues by getting updated.
现在,你可以通过在 Dockerfile 工作流中创建健壮且高效的容器化应用程序来针对速度、安全性和可维护性优化容器构建。
You can now optimize your container builds for speed, security, and maintainability by creating robust and efficient containerized applications built using best practices in Dockerfile workflows.
Dockerfile - Example
我们将编写一个 Dockerfile,用于一个简单的 Flask Web 应用程序,该应用程序提供消息“Hello, World!”。具体来说,我们将展示如何使用上面介绍的几条指令来创建和通过容器运行此应用程序。
We are going to write a Dockerfile for a simple Flask web application that serves the message 'Hello, World!' - and, in particular, we are going to show how to use several of the instructions above in the creation and running of this application via a container.
Dockerfile Code
# Use the official Python image as a base
FROM python:3.9-slim-buster
# Set environment variables
ENV PYTHONUNBUFFERED 1
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
# Set the working directory in the container
WORKDIR /app
# Copy the requirements file and install dependencies
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
# Copy the application code into the container
COPY . /app
# Expose port 5000 to the outside world
EXPOSE 5000
# Run the Flask app when the container launches
CMD ["flask", "run"]
Code Explanation
-
FROM python:3.9-slim-buster − This line sets the base image as the official Python 3.9 slim-buster image from Docker Hub - a lightweight image containing the necessary Python runtime.
-
ENV PYTHONUNBUFFERED 1 − Have the environment variable set up and make sure not to buffer the output, which helps in debugging.
-
ENV FLASK_APP=app.py − This specifies the main application file.
-
ENV FLASK_RUN_HOST=0.0.0.0 − The Flask app will be available to IP address 0.0.0.0.
-
WORKDIR /app − This line sets the working directory in the container to /app. Every other command from this point will be working in this directory.
-
COPY requirements.txt requirements.txt − This copies the requirements.txt file from your local machine to the /app directory within the container.
-
RUN pip install -r requirements.txt − This installs the listed Python package dependencies in the requirements.txt file.
-
COPY . /app − This copies the entire current directory (where your Dockerfile and application code reside) to the /app directory inside the container.
-
EXPOSE 5000 − This tells Docker that the container listens on port 5000 at runtime.
-
CMD ['flask', 'run'] − This is the default command that will be executed during the start of the container. It starts the Flask development server.
How Does It Work?
您需要生成一个 requirements.txt 文件,其中列出 Flask 应用程序的所有依赖项,例如 Flask。您在与 Flask 应用程序代码(app.py)的同一目录中将此 Dockerfile 保存为 Dockerfile,并且不带文件扩展名。然后,您可以通过执行命令 docker build -t my-flask-app 来创建 Docker 镜像。(将 my-flask-app 替换为您要为镜像指定的名称)。
You would generate a requirements.txt file that lists all the dependencies of your Flask application, such as Flask. You’d save this Dockerfile, with no file extension, as a Dockerfile in the same directory with your Flask application code (app.py). Then, you create the Docker image by executing the command docker build -t my-flask-app. (replace my-flask-app with the name you want to give to your image).
最后,您可以使用 docker run -p 5000:5000 my-flask-app 来运行容器。这将启动 Flask 应用程序,您可以在 http://localhost:5000/ 中通过浏览器访问它。这样,您的应用程序将运行在可移植和可重现的环境中,可以在不同的环境中轻松部署和管理。
Finally, you would run the container using docker run -p 5000:5000 my-flask-app. This will start the Flask application, and you can access it through your browser at http://localhost:5000/. This way, your application will run in a portable and reproducible environment, which can be easily deployed and managed across different environments.
Conclusion
总之,Docker 改变了我们进行应用程序开发、部署和整体管理的方式。通过 Docker 实现容器化,帮助开发者在各种不同的环境中实现更高的可移植性、可扩展性和一致性。简单来说,Dockerfile 是容器化的单元;如果没有 Dockerfile,组件和配置将无从谈起。
In summary, Docker has changed the world in the way we do development, deployment, and overall management of applications. Containerization, through Docker, has helped developers to be more portable, scalable, and consistent across a variety of different environments. In simple words, Dockerfiles are the units of containerization; without Dockerfiles, nothing will exist in terms of components and configurations.
我们在本文中学习了如何使用探索的最佳实践和示例使 Dockerfile 有效且安全。优化镜像大小、利用构建缓存并遵循安全准则,以便我们的应用程序在任何 Docker 环境中都能顺畅可靠地运行。之后,请记住,掌握 Dockerfile 是释放 Docker 的全部能力并在单击之间减少数小时例行工作的方法。
We have learned in this article how to make Dockerfiles effective and safe using the explored best practices and examples. Optimize image size, leverage the build cache, and follow security guidelines so our applications run smoothly and dependably across any Docker environment. After that, just remember that mastering Dockerfiles is your way to unleash the full power of Docker and cut hours of routine work in a matter of a click.
FAQ
Q 1. What is a Dockerfile and why do you need it?
Dockerfile 或多或少是一个包含指令的纯文本文件。它提供了 Docker 镜像的构建蓝图,即容器的蓝图。Dockerfile 详细说明了要安装的所有内容,从操作系统基础到其他每个包依赖项,甚至指定容器启动时需要运行的命令。
A Dockerfile is more or less like a plain text file of instructions. It provides a blueprint for building Docker images, blueprints for containers. Dockerfiles detail everything to be installed, from the operating system base to every other package dependency, and even specify commands that need to run when the container starts.
Dockerfile 将使镜像创建过程变得高效,并且能够确保在多种环境中的一致性和可复制性。
Dockerfiles will make the image creation process efficient, with the assurance of consistency and reproducibility in several environments.
Q 2. What are some key instructions in a Dockerfile?
其中一些必要的指令有:FROM - 它定义了从中开始构建的基础镜像;RUN - 它执行包含在镜像构建过程中作为一部分的命令,例如软件安装;COPY - 它将文件或目录从本地机器复制到镜像;EXPOSE - 用于声明容器内应用程序将使用的端口;最后 CMD,它设置了容器启动时要运行的默认命令。
Some of the essential directives are: FROM - it defines the base image to start building from; RUN - which executes commands that are a part of the image build process, for example, software installation; COPY - to copy files or directories from your local machine to the image; EXPOSE - for declaring ports that the application inside the container will use; and finally CMD, which sets the default command to be run when the container starts.
Q 3. How are COPY and ADD different in a Dockerfile?
ADD 命令会在 Dockerfile 中将文件添加到您的镜像中。但是,ADD 和 COPY 之间存在重要的差异。COPY 是以透明且可预测的方式从本地机器将文件或目录传输到镜像的首选方法。
The ADD command adds files to your image in a Dockerfile. But, there are essential differences between ADD and COPY. COPY is the preferred way of transferring files or directories from your local machine to the image in a transparent and predictable manner.
ADD 的其他一些功能是能够从远程 URL 提取文件,甚至可以自动提取压缩档案,就像它对 .tar 或 .zip 文件所做的那样。这使得 ADD 看起来更加灵活,但它在提取方面的古怪行为通常导致 COPY 由于简单而更加受欢迎。
Some more features of ADD are the ability to fetch files from remote URLs and even automatically extract compressed archives, as it would do to .tar or .zip files. This makes ADD seem to be even more flexible, but its eerie behavior when it comes to extraction usually leads to COPY being much preferred for the sake of simplicity.
请注意,如果您必须下载远程文件,则通常应该使用 curl 或 wget 等下载工具将它们分隔成不同的 RUN 指令,以减少不必要的图像层。
Note that if you must download remote files, you should generally separate them into a different RUN instruction using some downloading tool like curl or wget to reduce unnecessary image layers.
Q 4. How can the Dockerfile be optimized for small images?
较小的图像会有所帮助,因为它们占用的空间更小,传输速度更快,启动也很快捷。为了最大程度地缩小图像尺寸,请使用一个最小的基础镜像,将多个 RUN 命令链接在一起以减少中间层的数量、运用多阶段构建、丢弃不需要的工件,以及清理在构建过程中使用的中间文件和软件包。
Smaller images will help because they occupy less space, are transferred quickly, and have a rapid startup. To minimize the image size above all, use a minimal base image, chain multiple RUN commands together to reduce the number of intermediate layers, employ multi-stage builds, dispose of artifacts that are not needed, and clean intermediate files and packages used during the build process.
Q 5. What is a Multi-stage build in Docker?
多阶段构建是指可以在一个 Dockerfile 中使用多个 FROM 指令进行指定。其核心思想是在一个阶段内构建应用程序,其中包含进行编译所需的全部工具和依赖关系;在下一个阶段,只将需要带入更小、可投入生产的镜像的最终工件。这样,最终的图像更小,因为构建环境并不是它的组成部分,部署也更有效率和安全。
Multi-stage builds mean that multiple FROM instructions can be used to be specified from within a single Dockerfile. The core idea is that it is possible to build the application within one stage, with all the tools and dependencies required for compilation and copy; in the next stage, only the final artifacts that need to be taken to a smaller, ready-for-production image. This way, the final image is smaller because the built environment is not part of it, and the deployment is efficient and safe.