在 docker 中找不到主机卷的路径

Can not find path to host volume in docker

我正在 spring 引导中开发一个应用程序,其中照片将上传到服务器,然后使用 url 从服务器读取。该应用程序位于 docker 和 tomcat 服务器上。据我了解,最好的方法是使用主机将照片存储在 docker 卷上。因此,我使用 docker-compose.yml 文件创建卷并提供主机路径。文件片段:

version: '3.8'
services:
  my-app:
    image: app
    environment:
      - _JAVA_OPTIONS=-Xmx512m -Xms256m
      - SPRING_PROFILES_ACTIVE=prod,api-docs
      .
      .
      .
    ports:
      - 8085:8085
    networks:
      default: 
        ipv4_address: 172.19.0.2
    volumes:
       - ./var/home/my-app:/var/lib/docker/containers/docker_my-app  //"path to the host:path to the docker container"

根据我在 Docker 网站 there 上读到的内容,这就是您应该如何创建到将存储照片的主机的路径,即在左侧到主机的路径,右边是容器的路径。问题是没有创建或没有路径,但我找不到它。我还有一个每次检查路径是否存在时都会运行的方法:

@PostConstruct
public void init() {
    if (!Files.exists(Paths.get("./var/home/my-app"))) {
        try {
            Files.createDirectory(root);
        } catch (IOException e) {
            throw new StorageException("Error initializing directory: " + e.getMessage());
        } 
}

这会抛出路径不存在。

所以,我有问题:

编辑

所以要说明我的问题。我想将文件保存在卷主机中,然后通过 URL 获取图像,例如localhost:8080/image/12/picture.png 我必须指定文件被删除的路径。方法 init() 检查路径是否存在,然后将路径分配给应保存文件的变量 root。

@PostConstruct
public void init() {
    if (isProd) {
        root = Paths.get("./var/home/my-app");
    } else {
        root = Paths.get("./uploads");
    }

    if (!Files.exists(root)) {
        try {
            Files.createDirectory(root);
        } catch (IOException e) {
            throw new StorageException("Error initializing directory: " + e.getMessage());
        }
    }
}

然后我这样保存文件:

Files.copy(inputStream, filePath, StandardCopyOption.REPLACE_EXISTING);  //filePath: ./upluads/image/12/picture.png

filePath 应包含名称中带有 id 的每张照片的主机路径和唯一文件夹。

您当前正在将文件夹 /var/home/my-app 从主机安装到容器内的文件夹 /var/lib/docker/containers/docker_my-app

因为您的应用程序 运行 在您编写的方法的容器中

@PostConstruct
public void init() {
    if (!Files.exists(Paths.get("./var/home/my-app"))) {
        try {
            Files.createDirectory(root);
        } catch (IOException e) {
            throw new StorageException("Error initializing directory: " + e.getMessage());
        } 
}

在容器文件系统中创建目录结构 /var/home/my-app

如果您的 Java 代码是为了将数据保存在文件夹 /var/home/my-app 下,您应该按以下方式创建卷:

volumes:
   - /var/home/my-app:/var/home/my-app

假设您的 check-method 在您的 Spring 应用程序中,即在 my-app 容器中,您需要检查

/var/lib/docker/containers/docker_my-app

文件夹,而不是

./var/home/my-app

文件夹:

@PostConstruct
public void init() {
  if (!Files.exists(Paths.get("/var/lib/docker/containers/docker_my-app"))) {
    try {
        Files.createDirectory(root);
    } catch (IOException e) {
        throw new StorageException("Error initializing directory: " + e.getMessage());
    } 
}

首次使用 volume-folder 时,应在主机上创建相应的文件夹(因为您使用 short-notation 作为卷定义)。 应创建的文件夹将位于 docker-compose.yml 文件旁边,名为 var/home/my-app

要能够根据提供的 url 创建子文件夹,例如 localhost:8080/image/12/picture.png,您需要定义端点 /image/{id}/{image_name},其中 id 是路径变量,image_name 是一个路径变量。

同样,您用于上传文件的 POST 请求需要有 id 路径变量,您可以在代码中将其转换为文件夹名称,如果没有则创建它现在。

关于你的第三个问题:

If host will be with read write permissions should I add something in docker-compose.yml file?

这取决于你是否定义了一个用户来隔离你的容器。 看看这里:https://docs.docker.com/engine/security/userns-remap/ 除非你做了这样的事情,否则容器内的进程是 运行 root 并且可以在你的主机上写入,无论是否缺少权限。

编辑以阐明由于 docker-compose.yml:

中的行而创建的文件夹
 - ./var/home/my-app:/var/lib/docker/containers/docker_my-app  //"path to the host:path to the docker container"

正如您对这一行的正确评论, ./var/home/my-app 是主机上的路径。 因为它以“.”开头它是一个相对路径,将从 docker-compose.yml 文件所在的当前位置开始。

第二部分:/var/lib/docker/containers/docker_my-app 是容器内的路径,映射到主机上的文件夹。 这是一个绝对路径,因为它以 '/' 开头。

您的应用程序放置在此文件夹 (/var/lib/docker/containers/docker_my-app) 中的任何内容都可以在您的主机(因此在您的 docker 容器之外)的另一个文件夹 (./var/home/my-app). 它们在您的硬盘驱动器上是相同的 space,一次是从容器内部访问,一次是从主机访问。

在 docker-container 中运行的应用程序中,您独占使用路径:/var/lib/docker/containers/docker_my-app.

在容器外部,因此在您的主机上,您只使用路径 ./var/home/my-app.

假设在您的主机上 docker-compose.yml 文件位于文件夹中:

/home/thortiede/docker/docker-compose.yml

然后你会在

下找到共享文件夹的内容
/home/thortiede/docker/var/home/my-app

如果您希望在 docker-container 中可以访问主机中的文件,您需要将它们放在该目录中。 然后,从 docker-container 中,您可以通过导航到 :

来访问这些文件
/var/lib/docker/containers/docker_my-app