我有一个基本容器,可以打开通往机器的
ssh
隧道。
最近我注意到容器已退出,并显示错误代码
255
,并显示一条错误消息,内容为 task already exists
:
"Id": "7eb92418992a1a1c3e44d6b47257dc503d4fa4d0f26050956533d617ac369479",
"Created": "2022-08-29T18:19:41.286843867Z",
"Path": "sh",
"Args": [
"-c",
"apk update && apk add openssh-client &&\n chmod 400 ~/.ssh/abc.pem\n while true; do \n exec ssh -o StrictHostKeyChecking=no -i ~/.ssh/abc.pem -nNT -L *:33333:localhost:5001 [email protected]; \n done"
],
"State": {
"Status": "exited",
"Running": false,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 0,
"ExitCode": 255,
"Error": "task 7eb92418992a1a1c3e44d6b47257dc503d4fa4d0f26050956533d617ac369479: already exists",
"StartedAt": "2022-08-30T19:43:58.575463029Z",
"FinishedAt": "2022-08-30T19:51:23.511624168Z"
},
更重要的是,尽管重启策略是
always
,但容器退出后,docker引擎并没有启动容器。
abc:
container_name: abc
image: alpine:latest
restart: always
command: >
sh -c "apk update && apk add openssh-client &&
chmod 400 ~/.ssh/${PEM_FILENAME}
while true; do
exec ssh -o StrictHostKeyChecking=no -i ~/.ssh/${PEM_FILENAME} -nNT -L *:33333:localhost:5001 abc@${IP};
done"
volumes:
- ./ssh:/root/.ssh:rw
expose:
- 33333
task already exists
?更新1:
重启策略仅在容器启动后生效 成功地。在这种情况下,启动成功意味着 容器已启动至少 10 秒且 Docker 已启动 监控它。这可以防止根本不启动的容器进入重新启动循环。
正弦我们有:
"StartedAt": "2022-08-30T19:43:58.575463029Z",
"FinishedAt": "2022-08-30T19:51:23.511624168Z"
然后
FinishedAt - StartedAt ~ 8 seconds < 10 seconds
这就是docker引擎没有重新启动容器的原因。我认为这不是一个好的逻辑。 docker 引擎应该有一个重试机制,例如在放弃之前至少重试 3 次。
我建议这个解决方案:
在空文件夹中创建
Dockerfile
:
FROM alpine:latest
RUN apk update && apk add openssh-client
构建图像:
docker build -t alpinessh .
使用
docker run
运行它:
docker run -d \
--restart "always" \
--name alpine_ssh \
-u $(id -u):$(id -g) \
-v $HOME/.ssh:/user/.ssh \
-p 33333:33333 \
alpinessh \
ssh -o StrictHostKeyChecking=no -i /user/.ssh/${PEM_FILENAME} -nNT -L :33333:localhost:5001 abc@${IP}
(确保设置您需要的环境变量)
使用 docker-compose 运行遵循相同的逻辑。
** 注意 **
在容器内映射
~/.ssh
并不是最好的主意。最好将密钥复制到其他位置并从那里使用它。原因是:在容器内,您是 root,容器在 ~/.ssh 中创建的任何文件都将由 root (uid=0) 创建/访问。例如 known_hosts
- 如果您还没有,您将获得 root 拥有的一个全新的。
因此,我将容器作为主机上的当前 UID:GID 运行。
这对我有用;
docker compose up -d
注意
Dockerfile