1. Overview
1.概述
We mount Docker volumes when we need to link container resources to a host. We can use different volumes, like named volumes or bind mounts. Moreover, whether they are persistent or not, we can use local or remote resources. However, when mounting, we may need to exclude, for example, some files or folders that aren’t required.
当我们需要将容器资源链接到主机时,我们会挂载Docker卷。我们可以使用不同的卷,如命名卷或绑定挂载。此外,无论它们是否是持久性的,我们都可以使用本地或远程资源。然而,在挂载时,我们可能需要排除,例如,一些不需要的文件或文件夹。
In this tutorial, we’ll learn how to exclude folders when mounting volumes with some Docker Compose examples.
在本教程中,我们将通过一些Docker Compose实例来学习如何在挂载卷时排除文件夹。。
2. Create a Nodejs Docker Image
2.创建一个Nodejs Docker镜像
So why do we need to exclude some files or a folder with Docker? First, let’s discuss Docker images.
那么,为什么我们需要用Docker排除一些文件或文件夹?首先,让我们讨论一下Docker镜像。
When we build an image, we usually add application files. To demonstrate, we’ll use Nodejs to create a Docker sample application.
当我们构建一个图像时,我们通常会添加应用程序文件。为了演示,我们将使用Nodejs来创建一个Docker 示例应用程序。
Once we set the main application, let’s have a look at our Dockerfile:
一旦我们设置了主程序,让我们看看我们的Dockerfile。
FROM node:12.18.1
ENV NODE_ENV=production
WORKDIR /app
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production
COPY . .
CMD [ "node", "server.js" ]
Now we can build the image which we’ll call, for instance, node-docker:
现在我们可以建立镜像,例如,我们将称之为node-docker。
$ docker build -t node-docker .
In this case, the build context is our local /app folder. However, it could be a set of files located in the specified path or URL, like a Git repository, for example.
在本例中,构建环境是我们的本地/app文件夹。然而,它也可以是位于指定路径或URL中的一组文件,比如说Git仓库。
When we build our Docker image, we’ll send the files to a Docker server where the image is stored. Docker creates a layered image based on commands such as copy or run.
当我们构建Docker镜像时,我们会将文件发送到存储镜像的Docker服务器上。Docker根据copy或run等命令创建一个分层镜像。
Let’s run the docker history command to see the different layers of an image:
让我们运行docker history命令,看看一个图像的不同层。
$ docker history --format "ID-> {{.ID}} | Created-> {{.CreatedSince}} | Created By-> {{.CreatedBy}} | Size: {{.Size}}" e870a50eed97
We can use the –format option to create a custom output and show info like the relevant commands or the size:
我们可以使用-format选项来创建一个自定义输出,并显示相关命令或大小等信息。
ID-> e870a50eed97 | Created-> 36 hours ago | Created By-> /bin/sh -c #(nop) CMD ["node" "server.js"] | Size: 0B
ID-> 708a43cd0ef2 | Created-> 36 hours ago | Created By-> /bin/sh -c #(nop) COPY dir:7cc2842dd32649457… | Size: 11.3MB
ID-> d49b84f48e41 | Created-> 36 hours ago | Created By-> /bin/sh -c npm install --production | Size: 14.7MB
ID-> a351be0717a1 | Created-> 36 hours ago | Created By-> /bin/sh -c #(nop) COPY multi:9959dc16241ba60… | Size: 80.7kB
ID-> 56b22d35f315 | Created-> 36 hours ago | Created By-> /bin/sh -c #(nop) WORKDIR /app | Size: 0B
ID-> c28b64493ce8 | Created-> 36 hours ago | Created By-> /bin/sh -c #(nop) ENV NODE_ENV=production | Size: 0B
ID-> f5be1883c8e0 | Created-> 2 years ago | Created By-> /bin/sh -c #(nop) CMD ["node"] | Size: 0B
3. Exclude Files and Folders From the Image Build
3.从图像生成中排除文件和文件夹
Let’s consider a situation where we have a large file, for example, a log, a zip, or a jar file. Or we might have files we don’t want to expose in the final build, such as secret keys or passphrases.
让我们考虑这样一种情况:我们有一个大文件,例如,一个日志、一个zip或一个jar文件。或者我们可能有不想在最终构建中暴露的文件,如秘密密钥或口令。
We can use the .dockerignore file to avoid sending these files to the Docker server. It works similarly to the .gitignore file.
我们可以使用.dockerignore文件来避免向Docker服务器发送这些文件。它的作用与.gitignore文件类似。
Suppose we have a file with a password in our project. We can create one, for example:
假设我们的项目中有一个带密码的文件。我们可以创建一个,比如说。
$ echo 'password' >secret.txt
Now, we want to exclude this file from our image. We can add it to our .dockerignore file:
现在,我们想把这个文件从我们的图像中排除。我们可以把它添加到我们的.dockerignore文件。
# Ignoring the password file
secret.txt
This way, we can exclude resources from the build context. Furthermore, following best practices, it improves performance. The image to upload will have a smaller size.
这样,我们就可以将资源从构建环境中排除。此外,遵循最佳实践,它可以提高性能。要上传的图片将有一个较小的尺寸。
Also, we won’t have cache invalidation issues of a new layer if, for example, we add a file to copy. We can also exclude folders with this approach:
另外,如果我们添加了一个要复制的文件,我们就不会有新层的缓存无效问题。我们还可以用这种方法排除文件夹。
# Ignore the logs directory
logs/
Let’s build the image again with the .dockerignore file. Then, we can start a container:
让我们用.dockerignore文件再次构建镜像。然后,我们可以启动一个容器。
$ docker run -d --publish 8000:8000 node-docker
Or, if we use Docker Compose, we can run docker-compose up with a docker-compose.yml file, for example:
或者,如果我们使用Docker Compose,我们可以运行docker-compose up,例如,用docker-compose.yml文件。
services:
node-app:
image: node-docker:latest
ports:
- 8080:8080
We can double-check by executing the bash command in our container:
我们可以通过在我们的容器中执行bash命令来仔细检查。
$ docker exec -it d8938bc93406 bash
Once inside the container, if we check the content, for example, with the ls command, no secret.txt file or other excluded resources must be in the running container.
一旦进入容器,如果我们检查内容,例如用ls命令,运行中的容器中必须没有secret.txt文件或其他排除的资源。
4. Exclude Files and Folders With Docker Volumes
4.用Docker卷排除文件和文件夹
We’ve seen how we can exclude files and folders while building an image. We might want to do the same with running containers that use volumes.
我们已经看到我们如何在构建镜像时排除文件和文件夹。我们可能希望在运行使用volumes的容器时也能这样做。
One of the reasons could be to add files or folders without impacting what we have in our host.
其中一个原因可能是要添加文件或文件夹,而不影响我们主机中的内容。
Let’s suppose that we now want to add a project folder to the Docker container. We could achieve it using a mount bind.
假设我们现在想在Docker容器中添加一个项目文件夹。我们可以使用mount bind来实现它。
Let’s make a Docker Compose example for that with our Nodejs application. Let’s look at the docker-compose.yml file:
让我们用我们的Nodejs应用程序做一个Docker Compose的例子。让我们看看docker-compose.yml文件。
services:
node-app:
build: .
ports:
- 8081:8080
volumes:
- .:/app
We can run our container in the root directory of the project:
我们可以在项目的根目录下运行我们的容器。
$ docker-compose up -d
The container starts, and as expected, if there are files or directories in the container to be mounted, Docker copies the contents into the volume.
容器启动后,正如预期的那样,如果容器中有要挂载的文件或目录,Docker会将内容复制到卷中。
Let’s say that now, for some reason, we delete a file or a folder in our container. The same result happens in our host, and we’ll lose those resources.
假设现在由于某种原因,我们在容器中删除了一个文件或一个文件夹。同样的结果也会发生在我们的主机上,我们会失去这些资源。
Let’s see a couple of solutions to avoid deleting resources in our host.
让我们看看避免删除主机中资源的几个解决方案。
4.1. Exclude Files
4.1.排除文件
We can start by excluding the mount of a file in a container. Once we set the volume, we can do a workaround using the /dev/null command:
我们可以从排除容器中的文件的挂载开始。一旦我们设置了卷,我们就可以使用/dev/null命令做一个变通。
Again, let’s see our docker-compose.yml file:
再次,让我们看看我们的docker-compose.yml文件。
services:
node-app:
build: .
ports:
- 8080:8080
volumes:
- .:/app/
- /dev/null:/app/secret.txt
When using /dev/null, we discard anything written to a file. In this case, we’ll end up with secret.txt being empty. Moreover, there’s no way to modify the file due to its bind to /dev/null.
当使用/dev/null时,我们会丢弃任何写入文件的东西。在这种情况下,我们最终会发现secret.txt是空的。此外,由于该文件与/dev/null绑定,所以没有办法修改它。
4.2. Exclude Folders
4.2.排除文件夹
More interestingly, we can exclude folders and sub-folders. We can achieve that by creating an anonymous or named volume over that particular directory or sub-directory.
更有趣的是,我们可以将文件夹和子文件夹排除在外。我们可以通过在该特定目录或子目录上创建一个匿名或命名的卷来实现。
Let’s look at our YAML file:
让我们看一下我们的YAML文件。
services:
node-app:
build: .
ports:
- 8080:8080
volumes:
- .:/app
- /app/node_modules/
The order here is relevant. First, we have our bind over the /app directory we created earlier. Then, we mount a volume for what we want to exclude, in this case, the /node_modules sub-directory.
这里的顺序是相关的。首先,我们在之前创建的/app目录上进行绑定。然后,我们为我们想要排除的东西挂载一个卷,在这种情况下,/node_modules子目录./strong>。
If we were to persist our data, we could use a named volume:
如果我们要持久化我们的数据,我们可以使用一个命名卷。
volumes:
- .:/app
- my-vol:/app/node_modules/
volumes:
my-vol:
driver: local
Finally, we can try to modify the content of the /node_modules directory in the container. In this case, there will be no impact on our host.
最后,我们可以尝试修改容器中/node_modules目录的内容。在这种情况下,将不会对我们的主机产生影响。
5. Conclusion
5.总结
In this article, we learned how to exclude resources like files or folders with Docker. We looked at examples starting from an image build to running containers. For containers, we saw examples using Docker Compose and the possibility of using volumes to exclude sub-folders.
在这篇文章中,我们学习了如何用Docker排除文件或文件夹等资源。我们看了一些例子,从镜像构建到运行容器。对于容器,我们看到了使用Docker Compose的例子以及使用卷来排除子文件夹的可能性。
As always, we can find working code examples over on GitHub.
一如既往,我们可以在GitHub上找到工作代码的例子,。