如何在 docker compose 中将主机目录挂载为卷
Posted
技术标签:
【中文标题】如何在 docker compose 中将主机目录挂载为卷【英文标题】:How do I mount a host directory as a volume in docker compose 【发布时间】:2017-04-15 19:16:29 【问题描述】:我有一个正在 dockerizing 的开发环境,我希望能够实时重新加载我的更改,而无需重新构建 docker 映像。我正在使用 docker compose,因为 redis 是我的应用程序的依赖项之一,我喜欢能够链接 redis 容器
我在docker-compose.yml
中定义了两个容器:
node:
build: ./node
links:
- redis
ports:
- "8080"
env_file:
- node-app.env
redis:
image: redis
ports:
- "6379"
我已经在我的node
应用程序的 dockerfile 中添加了一个卷,但是如何将主机的目录挂载到卷中,以便我对代码的所有实时编辑都反映在容器中?
这是我当前的 Dockerfile:
# Set the base image to Ubuntu
FROM node:boron
# File Author / Maintainer
MAINTAINER Amin Shah Gilani <amin@gilani.me>
# Install nodemon
RUN npm install -g nodemon
# Add a /app volume
VOLUME ["/app"]
# TODO: link the current . to /app
# Define working directory
WORKDIR /app
# Run npm install
RUN npm install
# Expose port
EXPOSE 8080
# Run app using nodemon
CMD ["nodemon", "/app/app.js"]
我的项目如下所示:
/
- docker-compose.yml
- node-app.env
- node/
- app.js
- Dockerfile.js
【问题讨论】:
【参考方案1】:这是我的 Node.js 应用程序和 MongoDB 数据库的工作示例:
docker-compose.yml
version: '3'
services:
my-app:
container_name: my-app-container
restart: always
build: .
volumes:
- './storage:/usr/src/app/storage'
ports:
- "3000:3000"
links:
- my-app-db
my-app-db:
container_name: my-app-db-container
image: mongo
restart: always
volumes:
- './data:/data/db'
ports:
- "27017:27017"
Dockerfile
FROM node:16.13.2
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY package.json ./
RUN npm install
COPY . /usr/src/app/
EXPOSE 3000
CMD [ "npm", "start"]
【讨论】:
【参考方案2】:查看他们的documentation
从外观上看,您可以在 docker-compose.yml 上执行以下操作
volumes:
- ./:/app
其中./
是主机目录,/app
是容器的目标目录。
编辑:以前的文档源现在指向版本历史记录,您必须选择您正在使用的 compose 版本并查找参考。
对于懒人 – v3 / v2 / v1
旁注:截至本次编辑的所有版本的语法保持不变
【讨论】:
试过了,不行:Error: Cannot find module '/data/app.js'
等等.. 你的 VOLUME 和 WORKDIR 指向 /app/
为什么你的 CMD 指向 /data
这是一个错误!谢谢你抓住它!已修复,现在我收到 Error: Cannot find module 'express'
我现在要尝试一些事情。
对于 windows 容器,你需要一个 windows 风格的路径,比如 - .:c:/app
(这让我很头疼)
我的当前目录中有很多东西,但卷目录中没有任何内容。卷:- .:/stocks【参考方案3】:
在 docker-compose.yml 中你可以使用这种格式:
volumes:
- host directory:container directory
根据他们的documentation
【讨论】:
这个volume
属于services
部分还是独立部分?【参考方案4】:
在我们提及之前,我们必须创建您自己的docker卷映射到主机目录 strong>docker-compose.yml 作为 外部
1.创建名为share
的卷docker volume create --driver local \
--opt type=none \
--opt device=/home/mukundhan/share \
--opt o=bind share
2.在你的 docker-compose 中使用它
version: "3"
volumes:
share:
external: true
services:
workstation:
container_name: "workstation"
image: "ubuntu"
stdin_open: true
tty: true
volumes:
- share:/share:consistent
- ./source:/source:consistent
working_dir: /source
ipc: host
privileged: true
shm_size: '2gb'
db:
container_name: "db"
image: "ubuntu"
stdin_open: true
tty: true
volumes:
- share:/share:consistent
working_dir: /source
ipc: host
这样我们可以与运行在不同容器中的许多服务共享同一个目录
【讨论】:
为什么需要ipc:host? 只有当我们需要将网络绑定到主机本身时才需要。【参考方案5】:有两件事:
我在docker-compose.yml
添加了音量:
node:
volumes:
- ./node:/app
我将 npm install && nodemon app.js
部分移动到 CMD
中,因为 RUN
将内容添加到联合文件系统,而我的卷不是 UFS 的一部分。
# Set the base image to Ubuntu
FROM node:boron
# File Author / Maintainer
MAINTAINER Amin Shah Gilani <amin@gilani.me>
# Install nodemon
RUN npm install -g nodemon
# Add a /app volume
VOLUME ["/app"]
# Define working directory
WORKDIR /app
# Expose port
EXPOSE 8080
# Run npm install
CMD npm install && nodemon app.js
【讨论】:
【参考方案6】:如果您想在 Docker Compose YAML 文件的 volumes
部分中将特定主机目录(以下示例中的 /disk1/prometheus-data
)挂载为卷,您可以按照以下方式进行操作,例如:
version: '3'
services:
prometheus:
image: prom/prometheus
volumes:
- prometheus-data:/prometheus
volumes:
prometheus-data:
driver: local
driver_opts:
o: bind
type: none
device: /disk1/prometheus-data
顺便说一下,在 prometheus 的 Dockerfile 中,您可能会发现 VOLUME
指令如下,将其标记为从本机主机等外部挂载的卷。(但请注意:此指令不是必须的,但要挂载卷到容器中。):
Dockerfile
...
VOLUME ["/prometheus"]
...
参考:
https://docs.docker.com/compose/compose-file/#driver https://docs.docker.com/compose/compose-file/#driver_opts【讨论】:
这行得通。谢谢。local
驱动程序类型的文档在哪里?
@mmell 该文档是第一个 Refs 链接 (docs.docker.com/compose/compose-file/#driver),内容为:指定应为该卷使用的卷驱动程序。默认为 Docker 引擎配置使用的任何驱动程序,在大多数情况下为 local
@mmell,您可以从这个问题中找到更多详细信息:***.com/questions/42195334/…
@mmell 基本上,这些选项是依赖于驱动程序的,Linux 上的内置 local
驱动程序接受类似于 linux mount 命令的选项:man7.org/linux/man-pages/man8/mount.8.html。你可以在github.com/moby/moby/issues/19990#issuecomment-248955005和***.com/questions/35841241/…找到更多讨论
这个答案应该是一个关于如何跨多个容器挂载主机目录的单独问题的公认答案;很难找到这个!【参考方案7】:
有几个选项
短句法
使用host : guest
格式,您可以执行以下任何操作:
volumes:
# Just specify a path and let the Engine create a volume
- /var/lib/mysql
# Specify an absolute path mapping
- /opt/data:/var/lib/mysql
# Path on the host, relative to the Compose file
- ./cache:/tmp/cache
# User-relative path
- ~/configs:/etc/configs/:ro
# Named volume
- datavolume:/var/lib/mysql
长语法
从 docker-compose v3.2 开始,您可以使用长语法,该语法允许配置可以以短格式表示的附加字段,例如 mount type
(volume、bind 或 tmpfs)和 read_only
。
version: "3.2"
services:
web:
image: nginx:alpine
ports:
- "80:80"
volumes:
- type: volume
source: mydata
target: /data
volume:
nocopy: true
- type: bind
source: ./static
target: /opt/app/static
networks:
webnet:
volumes:
mydata:
查看https://docs.docker.com/compose/compose-file/#long-syntax-3 了解更多信息。
【讨论】:
为了补充您的答案,短语法中还有:cached
和 :delegated
注释。如果主机是 Docker Desktop for Mac,这些很重要。它们记录在 docker-docs.netlify.app/docker-for-mac/osxfs-caching 中,但不幸的是不在 Docker Compose 文档中。以上是关于如何在 docker compose 中将主机目录挂载为卷的主要内容,如果未能解决你的问题,请参考以下文章
使用 docker-compose 时如何在容器内使用主机用户修改卷文件