从 docker 容器写入 google-cloud-composer 中的文件
write a file from a docker container in google-cloud-composer
一些背景:
我正在使用 composer-1.3.0-airflow-1.10.0
已安装 PyPi 包docker===2.7.0
有一段时间我尝试使用 DockerOperator,但我需要从位于另一个 gcp 项目中的私有 gcr.io 注册表中拉取图像,那是一团糟。
我不会详细说明我为什么放弃这个。我切换到一个简单的 PythonOperator
用于拉取和 运行 docker 图像。操作员的运行方式如下:
def runImage(**kwargs):
workingDir = "/app"
imageName = "eu.gcr.io/private-registry/image"
volume = {"/home/airflow/gcs/data/": {"bind": "/out/", "mode": "rw"}}
userUid = os.getuid()
command = getContainerCommand()
client = getClient()
print("pulling image")
image = pullDockerImage(client, imageName)
print("image pulled. %s", image.id)
output = client.containers.run(
image=imageName,
command=command,
volumes=volume,
privileged=True,
working_dir=workingDir,
remove=True,
read_only=False,
user=userUid)
print output
return True
task = PythonOperator(
task_id="test_pull_docker_image",
python_callable=runImage,
dag=dag
)
图片拉的很好。它 运行 (这已经是胜利了)。
容器将一些文件写入 /out/
,我使用 rw
权限将其作为卷安装到 /home/airflow/gcs/data
。
添加了 working_dir, user, privileged, read_only
选项用于测试,但我认为它们不相关。
文件未创建。
直接在 pyhton 中将文件写入 /home/airflow/gcs/data
就可以了。
容器本身是编译的 C#。
在本地,如果容器无法写入文件,我会收到错误消息(如 Unhandled Exception: System.UnauthorizedAccessException: Access to the path '/out/file.txt' is denied. ---> System.IO.IOException: Permission denied
)
但是当我 运行 airlfow composer 中的 DAG 时,一切看起来都很好,容器输出符合预期,没有出现错误。
也许 Dockerfile 可能有用:
FROM microsoft/dotnet:2.1-sdk AS build-env
WORKDIR /app
# Copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore
# Copy everything else and build
COPY . ./
RUN dotnet publish -c Release -o out
# Build runtime image
FROM microsoft/dotnet:2.1-sdk
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "programm.dll"]
所以问题是,
为什么不写入文件?以及如何让容器写入文件到/home/airflow/gcs/data
?
所以我解决了这个问题,感谢
这里的答案分为两部分:
/home/airflow/gcs
是 gcsfuse 卷。将此目录用于 DockerVolume 只是行不通(可以通过添加插件来工作,我为此丢失了 link :/ )
我们想在 airflow-workers 中添加一个卷,我们可以通过更新 kubectl 配置来实现:
有关如何更新配置的信息,请参阅 。
我们要添加一个主机路径:
containers:
...
securityContext:
privileged: true
runAsUser: 0
capabilities:
add:
- SYS_ADMIN
...
volumeMounts:
- mountPath: /etc/airflow/airflow_cfg
name: airflow-config
- mountPath: /home/airflow/gcs
name: gcsdir
- mountPath: /var/run/docker.sock
name: docker-host
- mountPath: /bin/docker
name: docker-app
- mountPath: /path/you/want/as/volume
name: mountname
...
volumes:
- configMap:
defaultMode: 420
name: airflow-configmap
name: airflow-config
- emptyDir: {}
name: gcsdir
- hostPath:
path: /path/you/want/as/volume
type: DirectoryOrCreate
name: mountname
- hostPath:
path: /var/run/docker.sock
type: ""
name: docker-host
- hostPath:
path: /usr/bin/docker
type: ""
name: docker-app
现在我们可以在 DAG 定义中使用
volume = {"/path/you/want/as/volume": {"bind": "/out/", "mode": "rw"}}
文件将存在于 POD 中,您可以使用另一个任务将它们上传到 gcs 存储桶中。
希望能有所帮助:)
一些背景:
我正在使用 composer-1.3.0-airflow-1.10.0
已安装 PyPi 包docker===2.7.0
有一段时间我尝试使用 DockerOperator,但我需要从位于另一个 gcp 项目中的私有 gcr.io 注册表中拉取图像,那是一团糟。
我不会详细说明我为什么放弃这个。我切换到一个简单的 PythonOperator
用于拉取和 运行 docker 图像。操作员的运行方式如下:
def runImage(**kwargs):
workingDir = "/app"
imageName = "eu.gcr.io/private-registry/image"
volume = {"/home/airflow/gcs/data/": {"bind": "/out/", "mode": "rw"}}
userUid = os.getuid()
command = getContainerCommand()
client = getClient()
print("pulling image")
image = pullDockerImage(client, imageName)
print("image pulled. %s", image.id)
output = client.containers.run(
image=imageName,
command=command,
volumes=volume,
privileged=True,
working_dir=workingDir,
remove=True,
read_only=False,
user=userUid)
print output
return True
task = PythonOperator(
task_id="test_pull_docker_image",
python_callable=runImage,
dag=dag
)
图片拉的很好。它 运行 (这已经是胜利了)。
容器将一些文件写入 /out/
,我使用 rw
权限将其作为卷安装到 /home/airflow/gcs/data
。
添加了 working_dir, user, privileged, read_only
选项用于测试,但我认为它们不相关。
文件未创建。
直接在 pyhton 中将文件写入 /home/airflow/gcs/data
就可以了。
容器本身是编译的 C#。
在本地,如果容器无法写入文件,我会收到错误消息(如 Unhandled Exception: System.UnauthorizedAccessException: Access to the path '/out/file.txt' is denied. ---> System.IO.IOException: Permission denied
)
但是当我 运行 airlfow composer 中的 DAG 时,一切看起来都很好,容器输出符合预期,没有出现错误。
也许 Dockerfile 可能有用:
FROM microsoft/dotnet:2.1-sdk AS build-env
WORKDIR /app
# Copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore
# Copy everything else and build
COPY . ./
RUN dotnet publish -c Release -o out
# Build runtime image
FROM microsoft/dotnet:2.1-sdk
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "programm.dll"]
所以问题是,
为什么不写入文件?以及如何让容器写入文件到/home/airflow/gcs/data
?
所以我解决了这个问题,感谢
这里的答案分为两部分:
/home/airflow/gcs
是 gcsfuse 卷。将此目录用于 DockerVolume 只是行不通(可以通过添加插件来工作,我为此丢失了 link :/ )
我们想在 airflow-workers 中添加一个卷,我们可以通过更新 kubectl 配置来实现:
有关如何更新配置的信息,请参阅
containers:
...
securityContext:
privileged: true
runAsUser: 0
capabilities:
add:
- SYS_ADMIN
...
volumeMounts:
- mountPath: /etc/airflow/airflow_cfg
name: airflow-config
- mountPath: /home/airflow/gcs
name: gcsdir
- mountPath: /var/run/docker.sock
name: docker-host
- mountPath: /bin/docker
name: docker-app
- mountPath: /path/you/want/as/volume
name: mountname
...
volumes:
- configMap:
defaultMode: 420
name: airflow-configmap
name: airflow-config
- emptyDir: {}
name: gcsdir
- hostPath:
path: /path/you/want/as/volume
type: DirectoryOrCreate
name: mountname
- hostPath:
path: /var/run/docker.sock
type: ""
name: docker-host
- hostPath:
path: /usr/bin/docker
type: ""
name: docker-app
现在我们可以在 DAG 定义中使用
volume = {"/path/you/want/as/volume": {"bind": "/out/", "mode": "rw"}}
文件将存在于 POD 中,您可以使用另一个任务将它们上传到 gcs 存储桶中。
希望能有所帮助:)