使用 gcsfuse 挂载谷歌存储时 Docker 构建失败

Posted

技术标签:

【中文标题】使用 gcsfuse 挂载谷歌存储时 Docker 构建失败【英文标题】:Docker build failing when using gcsfuse to mount google storage 【发布时间】:2017-05-26 02:35:56 【问题描述】:

我一直在尝试将 SQL 和存储桶安装到我的 docker WordPress 容器中。它似乎成功安装 SQL,但未能安装存储桶。该实例基于this post。

我在下面附上了 Docker 文件和错误,以及我的构建命令。

构建命令:

docker build -t ic/spm .

Dockerfile:

FROM wordpress
MAINTAINER Gareth Williams <gareth@itinerateconsulting.com>

# Move login creds locally
ADD ./creds.json /creds.json

# install sudo, wget and gcsfuse
ENV GCSFUSE_REPO=gcsfuse-jessie
RUN   apt-get update && \
      apt-get -y install sudo && \
      apt-get install -y curl ca-certificates && \
      echo "deb http://packages.cloud.google.com/apt $GCSFUSE_REPO main" > /etc/apt/sources.list.d/gcsfuse.list && \
      curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - && \
      apt-get update && \
      apt-get install -y gcsfuse wget && \
      apt-get remove -y curl --purge && \
      apt-get autoremove -y && \
      rm -rf /var/lib/apt/lists/*

# Config fuse
RUN chmod a+r /etc/fuse.conf
RUN perl -i -pe 's/#user_allow_other/user_allow_other/g' /etc/fuse.conf

# Setup sql proxy
RUN sudo mkdir /cloudsql
RUN sudo chmod 777 /cloudsql
ADD https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64 cloud_sql_proxy.linux.amd64
RUN mv cloud_sql_proxy.linux.amd64 cloud_sql_proxy && chmod +x ./cloud_sql_proxy
RUN ./cloud_sql_proxy -dir=/cloudsql -fuse -credential_file=/creds.json &
# mysql -u icroot -S /cloudsql/[INSTANCE_CONNECTION_NAME]

# Perform Cloud Storage FUSE mounting for uploads folder
RUN mkdir /mnt/uploads
RUN chmod a+w /mnt/uploads
#RUN chown www-data:www-data -R /mnt && groupadd fuse && gpasswd -a www-data fuse && chmod g+rw /dev/fuse
USER www-data
RUN gcsfuse --key-file /creds.json \
  --debug_gcs --debug_http --debug_fuse --debug_invariants \
  --dir-mode "777" -o allow_other spm-bucket /mnt/uploads

错误:

Step 17 : RUN gcsfuse --key-file /creds.json   --foreground --debug_gcs --debug_http --debug_fuse --debug_invariants   --dir-mode "777" -o allow_other spm-bucket /mnt/uploads
 ---> Running in 7e3f31221bee
Using mount point: /mnt/uploads
Opening GCS connection...
Opening bucket...
gcs: Req              0x0: <- ListObjects()
http: ========== REQUEST:
GET http://www.googleapis.com/storage/v1/b/spm-bucket/o?maxResults=1&projection=full HTTP/1.1
Host: www.googleapis.com
User-Agent: gcsfuse/0.0
Authorization: Bearer ya29.ElrQAw8oxClKt8YGvtmxhc7z2Y2LufvL0fBueq1UESjYYjRrdxukNTQqO1qfM8e8h-rqfbOWNSjVK2rCRXVrEDla-CiUVhHwT6X71Y1Djb0jDJg7z3KblgNQPrc
Accept-Encoding: gzip

http: ========== RESPONSE:
HTTP/2.0 200 OK
Content-Length: 31
Alt-Svc: quic=":443"; ma=2592000; v="35,34"
Cache-Control: private, max-age=0, must-revalidate, no-transform
Content-Type: application/json; charset=UTF-8
Date: Wed, 11 Jan 2017 09:19:05 GMT
Expires: Wed, 11 Jan 2017 09:19:05 GMT
Server: UploadServer
Vary: Origin
Vary: X-Origin
X-Guploader-Uploadid: AEnB2UpTqXhtHW906FFDTRsz4FjHjFu_E84wYhvt0zhaVFuMpqSY1fsd1XcrEcpsYBBwX1mqf0ZXRVWJH05ThtDQIfFKHd4PFw


 "kind": "storage#objects"

http: ====================
gcs: Req              0x0: -> ListObjects() (1.793169206s): OK
Mounting file system...
mountWithArgs: mountWithConn: Mount: mount: running fusermount: exit status 1

stderr:
fusermount: failed to open /dev/fuse: Operation not permitted

【问题讨论】:

您遇到了身份验证问题。我已经发布了一个类似的 q,其中包含更多细节。帮助查看 gcloud info 的结果,您是否验证了您的服务帐户?你能简单地添加 gcloud auth activate-service-account --key-file ***.com/questions/41685351/… @bw4sz 我刚试过,似乎没问题,我可以验证。我只能认为是和fuse有关,但我不知道它可能是什么。 你在什么平台上运行你的 docker? @mustaccio 我正在使用 Mac OSX,然后希望将图像推送到 Google 并通过 kubernetes 使用 您的 Dockerfile 有一个注释掉的 RUN 行,看起来应该可以解决问题?取消注释后会发生什么? 【参考方案1】:

默认情况下,Docker 不允许挂载其他存储(如 GCP)。您可以做的是在使用特权选项运行容器时,您可以使用存储进行挂载。

将此命令放入脚本文件(gcp.sh)并构建 docker 映像。

RUN gcsfuse --key-file /creds.json \
  --debug_gcs --debug_http --debug_fuse --debug_invariants \
  --dir-mode "777" -o allow_other spm-bucket /mnt/uploads

gcp.sh:

gcsfuse --key-file /creds.json --debug_gcs --debug_http --debug_fuse --debug_invariants --dir-mode "777" -o allow_other spm-bucket /mnt/uploads

和 Dockerfile:

FROM wordpress
MAINTAINER Gareth Williams <gareth@itinerateconsulting.com>

# Move login creds locally
ADD ./creds.json /creds.json

# install sudo, wget and gcsfuse
ENV GCSFUSE_REPO=gcsfuse-jessie
RUN   apt-get update && \
      apt-get -y install sudo && \
      apt-get install -y curl ca-certificates && \
      echo "deb http://packages.cloud.google.com/apt $GCSFUSE_REPO main" > /etc/apt/sources.list.d/gcsfuse.list && \
      curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - && \
      apt-get update && \
      apt-get install -y gcsfuse wget && \
      apt-get remove -y curl --purge && \
      apt-get autoremove -y && \
      rm -rf /var/lib/apt/lists/*

# Config fuse
RUN chmod a+r /etc/fuse.conf
RUN perl -i -pe 's/#user_allow_other/user_allow_other/g' /etc/fuse.conf

# Setup sql proxy
RUN sudo mkdir /cloudsql
RUN sudo chmod 777 /cloudsql
ADD https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64 cloud_sql_proxy.linux.amd64
RUN mv cloud_sql_proxy.linux.amd64 cloud_sql_proxy && chmod +x ./cloud_sql_proxy
RUN ./cloud_sql_proxy -dir=/cloudsql -fuse -credential_file=/creds.json &
# mysql -u icroot -S /cloudsql/[INSTANCE_CONNECTION_NAME]

# Perform Cloud Storage FUSE mounting for uploads folder
RUN mkdir /mnt/uploads
RUN chmod a+w /mnt/uploads
#RUN chown www-data:www-data -R /mnt && groupadd fuse && gpasswd -a www-data fuse && chmod g+rw /dev/fuse
USER www-data
COPY gcp.sh /home
RUN chmod +x /home/gcp.sh
CMD cd /home && ./gcp.sh

最后在构建镜像后使用 --privileged 选项运行容器 docker run --privileged

【讨论】:

【参考方案2】:

如果您在 GKE 上运行容器,并且想要使用 gcsfuse,则权限应自动在您的本地帐户中继承。另外......还有一个警告,您需要确保您运行的集群需要具有存储访问权限。因此,请确保您的集群已将存储权限设置为完全访问。这样 gcsfuse 可以将您的存储桶挂载到容器内的 GCS 上,而不必担心传递凭证文件和所有这些东西......使得实现非常简单。

在您的 docker 文件中...确保您正在执行 apt 命令来获取和安装 gcsfuse 应用程序。

我亲自制作了一个 shell 脚本,一旦实例启动,我就会调用它,它会挂载我需要的目录。

这样的……

Docker 入口

ENTRYPOINT ["/opt/entry.sh"]

entry.sh 脚本示例

gcsfuse [gcs bucket name] [local folder to mount as]

在生成 GKE 集群时,请务必添加存储范围

gcloud container clusters create [your cluster name] --scopes storage-full

希望对你有所帮助。

【讨论】:

【参考方案3】:

您的 www-data 在 dockerfile 中有权限问题:

#RUN chown www-data:www-data -R /mnt && groupadd fuse && gpasswd -a www-data fuse && chmod g+rw /dev/fuse

取消注释该行

【讨论】:

比以前使用过的线路并且恢复无效。问题似乎与 docker 权限有关。构建时没有标志可以作为 --privileged 运行 这是一个长期存在的问题,请检查this,总而言之,您只能通过运行具有增强功能的容器,安装所需的软件,然后从中创建映像来解决容器。 这应该是实际的答案。

以上是关于使用 gcsfuse 挂载谷歌存储时 Docker 构建失败的主要内容,如果未能解决你的问题,请参考以下文章

构建 docker 容器时 gcsfuse 无法挂载

使用 gcsfuse-mounted Bucket 中的数据在 Google Cloud 实例上运行 Docker

GCSFuse 提供范围未授权错误

GCP 存储桶可在 UI 中访问,但不能通过 Cloud Shell 中的 gcsfuse

在非特权的基于 Ubuntu 的 Docker 容器中使用 gcsfuse 拒绝权限

GCloud 中 Docker 中的 GCSFuse 安装失败