我的用例与其他有这个问题的用例略有不同,所以前面有一点描述:
我正在开发Google Cloud并且已经进行了#24; dockerized" Django app。部分应用程序依赖于使用gsutil将文件移入/移出Google存储桶。出于各种原因,我们不希望使用Google Container Engine来管理我们的容器。相反,我们希望通过启动其他Google Compute VM来水平扩展,这将反过来运行此Docker容器。与https://cloud.google.com/python/tutorials/bookshelf-on-compute-engine类似,但我们将使用容器而不是拉动git存储库。
VM将基于Debian基本映像构建,依赖项的启动和安装(例如Docker本身)将使用启动脚本(例如gcloud compute instances create some-instance --metadata-from-file startup-script=/path/to/startup.sh
)进行编排。
如果我手动创建VM,请使用sudo -s
进行提升,运行gsutil config -f
(在/root/.boto创建凭据文件),然后运行我的docker容器(请参阅下面的Dockerfile)< / p>
docker run -v /root/.boto:/root/.boto username/gs gsutil ls gs://my-test-bucket
然后它的工作原理。但是,这需要我的交互来创建boto文件。
我的问题是:如何将默认服务凭据传递给将在该新VM中启动的Docker容器?
gsutil开箱即用,即使是新鲜的&#34; Debian VM,因为它使用所有VM加载的默认计算引擎凭据。有没有办法使用这些凭据并将它们传递给docker容器?在新VM上第一次调用gsutil后,我注意到它创建了〜/ .gsutil和〜/ .config文件夹。不幸的是,在Docker中安装了这两个
docker run -v ~/.config/:/root/.config -v ~/.gsutil:/root/.gsutil username/gs gsutil ls gs://my-test-bucket
无法解决我的问题。它告诉我:
ServiceException: 401 Anonymous users does not have storage.objects.list access to bucket my-test-bucket.
最小的gsutil Dockerfile(不是我的):
FROM alpine
#install deps and install gsutil
RUN apk add --update \
python \
py-pip \
py-cffi \
py-cryptography \
&& pip install --upgrade pip \
&& apk add --virtual build-deps \
gcc \
libffi-dev \
python-dev \
linux-headers \
musl-dev \
openssl-dev \
&& pip install gsutil \
&& apk del build-deps \
&& rm -rf /var/cache/apk/*
CMD ["gsutil"]
添加:解决方法:
我已经解决了我的问题,但它非常迂回,所以如果可能的话,仍然对更简单的方式感兴趣。所有细节如下:
首先,描述:
我首先在Web控制台中创建了一个服务帐户。然后,我将JSON密钥文件(称为credentials.json)保存到存储桶中。在GCE VM的启动脚本中,我将该密钥文件复制到本地文件系统(gsutil cp gs://<bucket>/credentials.json /gs_credentials/
)。然后我启动我的docker容器,挂载该本地目录。然后,当docker容器启动时,它会运行一个脚本来验证credentials.json(在docker中创建一个.boto文件),导出BOTO_PATH =,最后我可以在Docker容器中执行gsutil操作。
以下是一个小工作示例的文件:
Dockerfile:
FROM alpine
#install deps and install gsutil
RUN apk add --update \
python \
py-pip \
py-cffi \
py-cryptography \
bash \
curl \
&& pip install --upgrade pip \
&& apk add --virtual build-deps \
gcc \
libffi-dev \
python-dev \
linux-headers \
musl-dev \
openssl-dev \
&& pip install gsutil \
&& apk del build-deps \
&& rm -rf /var/cache/apk/*
# install the gcloud SDK-
# this allows us to use gcloud auth inside the container
RUN curl -sSL https://sdk.cloud.google.com > /tmp/gcl \
&& bash /tmp/gcl --install-dir=~/gcloud --disable-prompts
RUN mkdir /startup
ADD gsutil_docker_startup.sh /startup/gsutil_docker_startup.sh
ADD get_account_name.py /startup/get_account_name.py
ENTRYPOINT ["/startup/gsutil_docker_startup.sh"]
gsutil_docker_startup.sh:采用单个参数,这是JSON格式服务帐户凭据文件的路径。该文件存在,因为主机上的目录已安装在容器中。
#!/bin/bash
CRED_FILE_PATH=$1
mkdir /results
# List the bucket, see that it gives a "ServiceException:401"
gsutil ls gs://<input bucket> > /results/before.txt
# authenticate the credentials- this creates a .boto file:
/root/gcloud/google-cloud-sdk/bin/gcloud auth activate-service-account --key-file=$CRED_FILE_PATH
# need to extract the service account which is like:
# <service acct ID>@<google project>.iam.gserviceaccount.com"
SERVICE_ACCOUNT=$(python /startup/get_account_name.py $CRED_FILE_PATH)
# with that service account, we can locate the .boto file:
export BOTO_PATH=/root/.config/gcloud/legacy_credentials/$SERVICE_ACCOUNT/.boto
# List the bucket and copy the file to an output bucket for good measure
gsutil ls gs://<input bucket> > /results/after.txt
gsutil cp /results/*.txt gs://<output bucket>/
get_account_name.py:
import json
import sys
j = json.load(open(sys.argv[1]))
sys.stdout.write(j['client_email'])
然后,GCE启动脚本(在VM启动时自动执行)是:
#!/bin/bash
# <SNIP>
# Install docker, other dependencies
# </SNIP>
# pull docker image
docker pull userName/containerName
# get credential file:
mkdir /cloud_credentials
gsutil cp gs://<bucket>/credentials.json /cloud_credentials/creds.json
# run container
# mount the host machine directory where the credentials were saved.
# Note that the container expects a single arg,
# which is the path to the credential file IN THE CONTAINER
docker run -v /cloud_credentials:/cloud_credentials \
userName/containerName /cloud_credentials/creds.json
答案 0 :(得分:1)
您可以为实例分配Specific Service Account,然后在代码中使用应用程序默认凭据。请在测试之前验证这些点。
身份验证令牌通过retrieved automatically by Application Default Credential通过Google Metadata Server,您的实例和Docker容器也可以使用。 无需管理任何凭据。
def implicit():
from google.cloud import storage
# If you don't specify credentials when constructing the client, the
# client library will look for credentials in the environment.
storage_client = storage.Client()
# Make an authenticated API request
buckets = list(storage_client.list_buckets())
print(buckets)
我也很快地在docker上进行了测试,并且表现出色
yann@test:~$ gsutil cat gs://my-test-bucket/hw.txt
Hello World
yann@test:~$ docker run --rm google/cloud-sdk gsutil cat gs://my-test-bucket/hw.txt
Hello World