host模式容器compose建立记录
需要一个host模式的容器,用来跑gpu程序。同时最好使用ssh来直接远程连接。
以前是直接建立容器然后手动安装ssh的。但是最近突然又不行了,不知道为什么。我知道原因是容器的systmctl不能使用。但是为什么以前能用呢?
一、安装结构
总之换成dockerfile来安装一遍。该dockercompose项目结构如下:
ssh_container/
├── Dockerfile
├── start.sh
├── docker-compose.yml
├── run.sh
├── .env
1.Dockerfile
FROM pytorch/pytorch:1.10.0-cuda11.3-cudnn8-devel
# 添加 NVIDIA GPG 公钥(解决 NO_PUBKEY 错误)
RUN apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/3bf863cc.pub
# 安装 openssh 和 vim
RUN apt update && apt install -y openssh-server vim && \
mkdir -p /var/run/sshd && \
ssh-keygen -A
COPY start.sh /start.sh
RUN chmod +x /start.sh
RUN sed -i 's/^#PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config && \
sed -i 's/^#PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config && \
sed -i 's/^UsePAM yes/UsePAM no/' /etc/ssh/sshd_config
WORKDIR /workspace
CMD ["/start.sh"]
2.docker-compose.yml
services:
ssh_container:
build: .
container_name: ${CONTAINER_NAME}
network_mode: host
runtime: nvidia # 旧版dockercompose使用gpu的用法,runtime里面需要有相应配置
environment:
- ROOT_PASSWD=${ROOT_PASSWD}
- SSH_PORT=${SSH_PORT}
- CUDA_VISIBLE_DEVICES=all
- NVIDIA_VISIBLE_DEVICES=all
volumes:
- ${WORKSPACE_HOST}:${WORKSPACE_CONTAINER}
stdin_open: true
tty: true
需要在宿主机的 /etc/docker/daemon.json
中配置:
{
"default-runtime": "nvidia",
"runtimes": {
"nvidia": {
"path": "nvidia-container-runtime",
"runtimeArgs": []
}
}
}
3.env
ROOT_PASSWD=root密码
SSH_PORT=ssh的端口
CONTAINER_NAME=容器名称
WORKSPACE_HOST=/home/workspace
WORKSPACE_CONTAINER=/workspace
4.run.sh
#!/bin/bash
read -s -p "请输入 root 密码:" ROOT_PASSWD
echo ""
read -p "请输入 SSH 端口号(默认 1523):" SSH_PORT
SSH_PORT=${SSH_PORT:-1523}
read -p "请输入容器名称(默认 by_1):" CONTAINER_NAME
CONTAINER_NAME=${CONTAINER_NAME:-by_1}
read -p "请输入主机挂载目录(默认 /home/workspace):" WORKSPACE_HOST
WORKSPACE_HOST=${WORKSPACE_HOST:-/home/workspace}
read -p "请输入容器挂载目录(默认 /workspace):" WORKSPACE_CONTAINER
WORKSPACE_CONTAINER=${WORKSPACE_CONTAINER:-/workspace}
cat > .env <<EOF
ROOT_PASSWD=$ROOT_PASSWD
SSH_PORT=$SSH_PORT
CONTAINER_NAME=$CONTAINER_NAME
WORKSPACE_HOST=$WORKSPACE_HOST
WORKSPACE_CONTAINER=$WORKSPACE_CONTAINER
EOF
docker compose up -d --build
5.start_static.sh
#!/bin/bash
if [ ! -f .env ]; then
echo "❌ ERROR: .env file not found."
exit 1
fi
export $(grep -v '^#' .env | xargs)
docker compose up -d --build
6.start.sh
#!/bin/bash
if [ -z "$ROOT_PASSWD" ]; then
echo "❌ ERROR: ROOT_PASSWD is not set."
exit 1
fi
PORT=${SSH_PORT:-1523}
echo "root:$ROOT_PASSWD" | chpasswd
sed -i "s/^#Port.*/Port $PORT/" /etc/ssh/sshd_config
sed -i "s/^Port.*/Port $PORT/" /etc/ssh/sshd_config
echo "✅ SSH starting on port $PORT..."
exec /usr/sbin/sshd -D -p $PORT
二、使用方法
设置可执行权限
chmod +x run.sh start_static.sh start.sh
动态交互启动:
./run.sh
使用 .env 静态启动
先手动编辑 .env 内容,再运行:
./start_static.sh
停止并清理容器
docker compose down
三、注意事项
1.ssh-keygen -A
会自动检查 /etc/ssh/
目录中是否存在有关主机密钥,如果缺失,就会自动生成.
很多官方 Ubuntu 镜像(或 PyTorch 镜像)里默认不生成这些密钥
如果没生成这些密钥就尝试运行 sshd
,它会报错或启动失败
2.容器实例生成相关
根据这些脚本生成了一个容器实例,并且能够正常运行。但是在想用同样的脚本与不同的.env环境再生成另一个容器时,docker关闭并删除了第一个容器,同时第二个容器也没有正常启动。
根本原因:Docker Compose 默认使用的是**“项目名 + 服务名”**作为容器名基础
如果再次用同样目录运行 docker compose up
:
-
Compose 会认为这是同一个项目
-
所以它会对已有服务进行 recreate(重建)
-
就算在
.env
中改了容器名,Docker Compose 本身只看当前目录 + 服务名
解决方法:将两个 Compose 项目放在不同的目录中
3.清理具体是做什么
它比单独 stop/rm 做的事更多:
docker compose down
相当于:
-
docker stop
所有由当前compose
项目启动的容器 -
docker rm
删除这些容器 -
同时删除它们使用的网络(默认 bridge)
-
清除匿名 volumes(如果加上
--volumes
参数)
所以它更“彻底”,用于清理整个 Compose 项目。