【问题标题】:Mounting a volume overwrites files stored in the Docker image挂载卷会覆盖存储在 Docker 映像中的文件
【发布时间】:2020-05-04 04:18:21
【问题描述】:

我正在尝试将我网站的前端容器化并自动化其部署。我的目标是能够在推送更改时生成和托管新图像,并让服务器自动获取它并重新启动容器。以下是我正在采取的步骤:

  1. 我首先构建我的 Node 应用程序,然后将分发和 nginx 配置文件捆绑到最新的linuxserver/letsencrypt 图像中来创建图像。这是 Dockerfile:

    # Use the NodeJS image as builder
    FROM node:alpine AS builder
    
    # Create the workspace
    RUN mkdir -p /usr/src/app
    WORKDIR /usr/src/app
    
    # Copy the package file and source code
    COPY package.json /usr/src/app
    COPY . ./
    
    # Install dependencies
    RUN npm install
    
    # Build the application
    RUN npm run build
    
    # The nginx server, this builds the final image
    FROM linuxserver/letsencrypt
    
    # Copy the nginx configuration
    COPY ./config/nginx.conf /config
    
    # Copy the output of the builder
    COPY --from=builder /usr/src/app/dist /config/www
    
    # Inform Docker to listen on port 443 and 80
    EXPOSE 443 80  
    
  2. 此图像已上传到 GitHub's package registry,我使用 Watchtower 轮询更新。

  3. 镜像是使用这个 docker-compose 文件启动的:

    version: "3"
    services:
      ...
      frontend:
        image: [IMAGE]
        container_name: frontend
        cap_add:
          - NET_ADMIN
        environment:
          - PUID=1000
          - PGID=1000
          - TZ=[TIMEZONE]
          - URL=[URL]
          - SUBDOMAINS=www,
          - VALIDATION=http
        ports:
          - 443:443
          - 80:80
        volumes:
          - ./frontend:/config
        restart: unless-stopped
      ...  
    

问题是当我在 docker-compose 中使用以下行时,使用 COPY 指令打包到映像中的文件被覆盖:

volumes:
  - ./frontend:/config  

如果我从 docker-compose 文件中删除该部分,一切正常,但这不是解决方案,因为该文件夹存储重要数据。

我已经读过安装卷会完全覆盖任何以前的数据,但是我喜欢这样一个事实,即我可以轻松地将图像加载到我的服务器上并且已经嵌入了所有必需的文件。有什么办法可以解决我的问题,还是我误用/误解了 docker 图像?

我已尝试按照here 的建议将音量设置为只读,但这不起作用,而是导致图像不断停止并重新启动。

我还简要了解了bind mounts,我想知道它们是否有用。

【问题讨论】:

    标签: docker nginx docker-compose dockerfile lets-encrypt


    【解决方案1】:

    这种行为是预期的。 Docker 挂载的工作方式与 Linux 挂载相同,即用源目录内容覆盖目标目录的内容。

    我的建议是为您的卷使用另一个目标目录,例如

    volumes:
     - ./frontend:/someotherdir 
    

    然后调整您的 nginx 配置以在那里查找 JS 文件。

    【讨论】:

      【解决方案2】:

      我发现我可以通过首先创建一个named volume来保留图像中的数据:

      volumes:
        frontend_data:
      

      然后将容器安装到该卷:

      services:
        frontend:
          ...
          volumes:
            - frontend_data:/config
          ...
      

      【讨论】:

      • 这仅在您第一次启动容器时有效;如果您更新映像中的配置文件,则卷将不会更新。 (如果您正在考虑在 Kubernetes 上部署它,这根本行不通。)
      • @DavidMaze 我意识到我可以使用docker cp 实用程序将文件复制出容器。虽然我可以将其集成到我的工作流程中,但您认为这是一种反模式吗?更一般地说,您会建议不要将我的数据嵌入到图像中吗?
      猜你喜欢
      • 2019-01-03
      • 2014-12-08
      • 1970-01-01
      • 2018-05-31
      • 2016-02-17
      • 2018-10-29
      • 2016-08-18
      • 2018-05-19
      • 1970-01-01
      相关资源
      最近更新 更多