Skip to main content

在 Docker 中使用 JuiceFS

如果你只是想在容器中访问 JuiceFS,那么最简单的用法是卷映射,在宿主机上挂载 JuiceFS,然后映射进容器里即可,假定挂载点为 /jfs

docker run -d --name nginx \
-v /jfs/html:/usr/share/nginx/html \
-p 8080:80 \
nginx

Docker 还给 JuiceFS 的使用带来很多其他可能性,挑选下方感兴趣的小节阅读。

在容器中挂载 JuiceFS

如果不方便在宿主机安装 JuiceFS 客户端,可以在容器中运行挂载进程,然后将挂载点导出到宿主机使用:

docker run -d --name=jfsmount --restart=always --privileged \
--mount type=bind,source=/mnt,target=/mnt,bind-propagation=shared \
-v /root/.juicefs/:/root/.juicefs \
-v /var/jfsCache:/var/jfsCache \
juicedata/mount:ee-4.9.23 juicefs mount myjfs /mnt/jfs -f

在上方的示范中:

  • 配置文件目录 /root/.juicefs 映射到了容器中,让容器内的 JuiceFS 客户端与宿主机共享配置文件
  • 缓存目录 /var/jfsCache 映射到了容器中,与宿主机共享缓存目录
  • 挂载命令添加 -f 参数,使之运行在前台,因此用 docker logs 查看容器日志,就是 JuiceFS 客户端日志
  • myjfs 文件系统被挂载到了容器内的 /mnt/jfs,然后按照挂载点传播设置,将挂载点导出到了宿主机,这样一来,宿主机也能通过 /mnt/jfs 访问文件系统

当象存储是 Ceph 时(仅在私有部署支持),JuiceFS 客户端依赖 Ceph 相关的动态链接库,这种场景也非常适合将挂载进程运行在容器中,宿主机就不需要特意安装相关动态链接库:

docker run -d --name=jfsmount --restart=always --privileged \
--mount type=bind,source=/mnt,target=/mnt,bind-propagation=shared \
-v /root/.juicefs/:/root/.juicefs \
-v /var/jfsCache:/var/jfsCache \
-v /etc/ceph:/etc/ceph \
--env BASE_URL=$JUICEFS_CONSOLE_URL/static \
juicedata/mount:ee-4.9.23 juicefs mount myjfs /mnt/jfs -f

在上方的示范中,几个额外需要注意的要点:

  • Ceph 的配置文件目录 /etc/ceph 映射到了容器中,与宿主机共享 Ceph 配置文件
  • 在私有部署集群中使用 JuiceFS 客户端,需要用环境变量 BASE_URL 覆盖 Web 控制台地址

卷插件

如果对挂载管理有着更高的要求,比如希望通过 Docker 来管理挂载点,方便不同的应用容器使用不同的 JuiceFS 文件系统,还可以通过卷插件(Docker volume plugin)与 Docker 引擎集成。

在 Docker 中,插件也是一个容器镜像,JuiceFS 卷插件镜像中内置了 JuiceFS 社区版以及 JuiceFS 云服务客户端,安装以后,便能够运行卷插件,在 Docker 中创建 JuiceFS Volume。

通过下面的命令安装插件,按照提示为 FUSE 提供必要的权限:

docker plugin install juicedata/juicefs

你可以使用以下命令管理卷插件:

# 停用插件
docker plugin disable juicedata/juicefs

# 升级插件(需先停用)
docker plugin upgrade juicedata/juicefs
docker plugin enable juicedata/juicefs

# 卸载插件
docker plugin rm juicedata/juicefs

创建 Volume

创建新的 Volume 时需要提供 JuiceFS 文件系统名称、密钥以及对象存储的访问凭据(如果不确定从哪里获取这些认证信息,可以重温创建文件系统),例如:

docker volume create -d juicedata/juicefs \
-o name=$VOL_NAME -o token=$JFS_TOKEN \
-o accesskey=$ACCESS_KEY -o secretkey=$SECRET_KEY jfsvolume

如果需要在认证、挂载文件系统时传入额外的环境变量(比如 Google 云存储),可以对上方命令追加类似 -o env=FOO=bar,SPAM=egg 的参数。

使用和管理存储卷

# 创建容器时挂载卷
docker run -it -v jfsvolume:/opt busybox ls /opt

# 删除存储卷,注意这仅仅是删除 Docker 中的对应资源,并不影响 JuiceFS 中存储的数据
docker volume rm jfsvolume

通过 Docker Compose 挂载

下面是使用 docker-compose 挂载 JuiceFS 文件系统的例子:

version: '3'
services:
busybox:
image: busybox
command: "ls /jfs"
volumes:
- jfsvolume:/jfs
volumes:
jfsvolume:
driver: juicedata/juicefs
driver_opts:
name: ${VOL_NAME}
token: ${JFS_TOKEN}
access-key: ${ACCESS_KEY}
secret-key: ${SECRET_KEY}
# 如有需要,可以用 env 传入额外环境变量
# env: FOO=bar,SPAM=egg

配置文件撰写完毕,可以通过下方命令创建和管理:

docker-compose up

# 关闭服务并从 Docker 中卸载 JuiceFS 文件系统
docker-compose down --volumes

在 Docker Swarm 中使用

JuiceFS 文件系统支持多节点的 Docker Swarm 集群。你需要确保 juicedata/juicefs 插件在所有工作节点上安装并启用。

JuiceFS 的挂载参数通过 --mount 指定,如下面的例子所示。

docker service create --name nginx --mount \
type=volume,volume-driver=juicedata/juicefs,source=jfsvolume,destination=/jfs, \
volume-opt=name=$VOL_NAME,volume-opt=token=$JFS_TOKEN,volume-opt=accesskey=$ACCESS_KEY,volume-opt=secretkey=$SECRET_KEY nginx:alpine

排查

无法正常工作时,推荐先升级卷插件,然后根据问题情况查看日志。

  • 收集 JuiceFS 客户端日志,日志位于 Docker 卷插件容器内,需要进入容器采集:

    # 确认 docker plugins runtime 目录,根据实际情况可能与下方示范不同
    # ls 打印出来的目录就是容器目录,名称为容器 ID
    ls /run/docker/plugins/runtime-root/plugins.moby

    # 打印 plugin 容器信息
    # 如果打印出的容器列表为空,说明 plugin 容器创建失败
    # 阅读下方查看 plugin 启动日志继续排查
    runc --root /run/docker/plugins/runtime-root/plugins.moby list

    # 进入容器,打印日志
    runc --root /run/docker/plugins/runtime-root/plugins.moby exec 452d2c0cf3fd45e73a93a2f2b00d03ed28dd2bc0c58669cca9d4039e8866f99f cat /var/log/juicefs.log

    如果发现容器不存在(ls 发现目录为空),或者在最后打印日志的阶段发现 juicefs.log 不存在,那么多半是挂载本身就失败了,继续查看 plugin 自身的日志寻找原因。

  • 收集 plugin 日志,以 systemd 为例:

    journalctl -f -u docker | grep "plugin="

    如果 plugin 调用 juicefs 发生错误,或者 plugin 自身报错,均会在日志里有所体现。