问题描述
这里有一些背景知识:我有一个Django应用程序运行在预先安装了Docker 19.03.1〜3的DigitalOcean Droplet上。我正在运行一个单节点群集集群,该应用程序在大多数情况下都可以正常运行。
这是我遇到的问题:我试图将一些管理命令放入手动触发的GitLab CI作业中,因此我不必通过SSH进入Droplet并运行命令(migrate
和{{ 1}})。当SSH进入Droplet时,我可以成功运行这些命令。例如,要运行collectstatic
,我将查找Django容器(collectstatic
)的容器ID,然后运行:
e710394e5449
要运行管理命令,我想我可以做这样的事情:
docker exec -it e710394e5449 python3 manage.py collectstatic
这是我在GitLab CI作业日志中看到的错误:
docker exec $(docker ps -q -f name="backend") python3 manage.py collectstatic --no-input
您可以从远程docker主机上的GitLab CI作业运行error during connect: Get http://docker/v1.40/containers/e710394e5449/json: command [ssh -l root 123.45.6.789 -- docker system dial-stdio] has exited with exit status 255,please make sure the URL is valid,and Docker 18.09 or later is installed on the remote host: stderr=ssh: connect to host 123.45.6.789 port 22: Connection refused
吗?我可以获取容器ID(docker exec
),但是外部$(docker ps -q -f name="backend")
命令失败。我可以从笔记本电脑上毫无问题地运行命令(docker exec
。
这是我的 docker exec $(docker ps -q -f name="backend") python3 manage.py collectstatic --no-input
文件。 .gitlab-ci.yml
作业为我如何运行命令提供了两个选项:一个使用django-collectstatic
在现有容器中运行该命令,另一个使用docker exec
。这些选项都不起作用,这只是为了展示我的尝试。
docker run
请告诉我是否还有其他事情可以帮助您澄清我的问题。
解决方法
到目前为止,我认为最简单的方法是直接通过SSH运行docker命令,而不是使用DOCKER_HOST
环境变量连接我的docker CLI(在GitLab CI中)。
这最终看起来像这样:
django-migrate:
before_script:
- apk update && apk add openssh-client bash
- mkdir -p ~/.ssh
- echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- eval "$(ssh-agent -s)"
- ssh-add ~/.ssh/id_rsa
- ssh-keyscan -H $DROPLET_IP >> ~/.ssh/known_hosts
stage: management
rules:
- when: manual
script:
- ssh root@$DROPLET_IP \
'docker exec $(docker ps -q -f name="backend") python3 manage.py migrate --no-input'
无论出于何种原因,运行docker exec $(docker ps -q -f name="backend") python3 manage.py migrate --no-input
都会失败。我将能够获得容器ID(docker ps
命令将成功完成,但是docker exec
命令将由于连接被拒绝而失败。
我不确定通过SSH连接运行docker命令的安全性。
该命令的输出确实很好地显示在GitLab CI作业的日志中,这正是我想要的。
,我回答了相同的问题here,您可以使用选项-h或DOCKER_HOST env在远程主机上运行docker命令,如果尚未完成,则需要启用TLS。