Docker容器化服务器搭建

总结下在实验室的服务器上搭建深度学习环境的过程,并通过docker创建不同开发需求的环境,实现本地远程连接。

安装Ubuntu系统

首先要给服务器安装Linux系统,服务器安装的是Ubuntu 18.04 /20.04 Server LTS,安装教程网上一大堆不做赘述了。安装完后要对系统进行一些配置:

更换软件源

  1. 备份原来的源。
sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup
  1. 打开/etc/apt/sources.list文件,在前面添加如下条目,并保存。
sudo vim /etc/apt/sources.list
#  阿里源
deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
  1. 更新源和软件
sudo apt-get update

sudo apt-get upgrade
  1. 安装一组必要的工具
sudo apt update
sudo apt install vim openssh-server bash-completion net-tools language-selector-gnome -y
  1. 卸载不需要的软件
sudo apt-get remove libreoffice-common unity-webapps-common \
thunderbird totem rhythmbox empathy brasero simple-scan gnome-mahjongg aisleriot \
gnome-mines cheese transmission-common gnome-orca gnome-sudoku   \
onboard deja-dup -y
  1. 更新系统
    • install the package maintainer's version: 安装软件包维护者所提供的版本
sudo apt dist-upgrade -y
  1. 重启系统
sudo reboot
  1. 安装必要的软件与依赖库
  • 必要软件
    • 下载工具
sudo apt install -y wget uget aria2 zip unzip rar unrar p7zip-full
  • 其他库
sudo apt install libeigen3-dev \
build-essential cmake git \
libgtk2.0-dev pkg-config libavcodec-dev \
libavformat-dev libswscale-dev libtbb2 \
libtbb-dev libjpeg-dev libpng-dev \
libtiff-dev libdc1394-22-dev libboost-all-dev \
libflann-dev libvtk6-dev libeigen3-dev \
liblapack-dev libsuitesparse-dev libcxsparse3 \
libgflags-dev libgoogle-glog-dev libgtest-dev  \
libeigen3-dev libgflags-dev libatlas-base-dev \
libeigen3-dev libsuitesparse-dev qt5-qmake \
libsuitesparse-dev libcxsparse3 libcholmod3 \
libtbb-dev python-jinja2 python3-jinja2 \
python3-pip python3-dev libqglviewer-headers \
libpcl1 libpcl1-dev -y

安装图形化桌面

方便基础差的同学运维管理服务器

sudo apt install ubuntu-desktop --no-install-recommends

网络问题

配置静态ip(适用于安装启用DHCP)

在某些场景下,我们可能需要将一台电脑的IP地址设置成静态的。例如在局域网内部署一个服务器,我们可能不希望他通过DHCP获取动态地址,而造成无法访问。设置静态IP在window系统下比较容易,但在Linux系统下稍微麻烦一点。

# 先查看网卡信息
ifconfig 

# 输入route -n命令,打印路由表,这里主要是为了查看网关地址,后续会用到
route -n 
# 更改00-installer-config.yaml文件配置
sudo vim /etc/netplan/00-installer-config.yaml

关闭IPV6(2023-10-2新增)

1. 使用如下参数临时关闭IPV6,设备重启后参数失效
sudo sysctl -w net.ipv6.conf.all.disable_ipv6=1
sudo sysctl -w net.ipv6.conf.default.disable_ipv6=1
sudo sysctl -w net.ipv6.conf.lo.disable_ipv6=1
2. 永久关闭IPV6的方法(两种)
# 1、打开/etc/sysctl.conf
# 2、添加如下三条设置
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
# 3、保存修改
# 4、执行:
sudo sysctl -p
# 备份/etc/default/grub文件
sudo cp -v /etc/default/grub /etc/default/grub.bak

# 修改/etc/default/grub配置 
# 编辑/etc/default/grub,在GRUB_CMDLINE_LINUX里面增加ipv6.disable=1参数
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash ipv6.disable=1"
GRUB_CMDLINE_LINUX="ipv6.disable=1"

疑难解答(2023-10-2新增):

  • 在面对多网卡的情况下,gateway只需要设置一遍,多次设置会导致路由表冲突。
root@zdcy-Super-Server:~# netplan apply

** (generate:5726): WARNING **: 11:25:46.530: Problem encountered while validating default route consistency.Please set up multiple routing tables and use `routing-policy` instead.
Error: Conflicting default route declarations for IPv4 (table: main, metric: default), first declared in br0 but also in br1

** (process:5724): WARNING **: 11:25:47.506: Problem encountered while validating default route consistency.Please set up multiple routing tables and use `routing-policy` instead.
Error: Conflicting default route declarations for IPv4 (table: main, metric: default), first declared in br0 but also in br1

netplan apply会根据gateway4生成默认路由,保留一个gateway4即可

Dell R740会有两个ip,一个为默认外网访问接口,一个为idrac管理接口。我们在配置过程中只需要保证外网访问接口畅通即可。

配置SSH链接

  • 查看是否安装了ssh-server服务。默认只安装ssh-client服务。
dpkg -l | grep ssh
  • 安装ssh-server服务
sudo apt-get install openssh-server
  • 确认ssh-server是否启动了:
ps -e | grep ssh

如果没有,可执行 sudo service ssh start,完成之后就可以SSH登录服务器(推荐使用MobaXterm)

宿主机SSH服务自启动
#ssh服务自启动命令
sudo systemctl enable ssh

#查看ssh服务状态,显示Active即代表成功
sudo systemctl status ssh

挂载硬盘(可选)

服务器一般多块硬盘,系统安装在其中一块硬盘。

  • 查看磁盘容量及分区状况(可以查看未挂载分区):sudo lsblk -f
  • 将机械硬盘格式化为 ext4: sudo mkfs.ext4 /dev/sda
  • 挂载硬盘:
  sudo mkdir /home/用户名/hhd
  sudo mount /dev/sda /home/用户名/hhd
  df -Th  # 磁盘容量及分区状况(不能查看未挂载分区)
  • 设置开机自动挂载,编辑 /etc/fstab ,在其内容中追加/dev/sda /home/用户名/hhd ext4 defaults 0 0
  • 重启后验证:lsblk -f

经常需要使用ssh工具传输文件,对挂载的目录添加写入权限:sudo chmod 777 目录名。注意必须要精确到改目录下(改变其上级目录权限都不行)

配置Samba共享文件服务(2023-10-2新增)

安装Samba服务

为了方便同学们的工程开发,首先在宿主机本地创建文件共享文件夹data

sudo mkdir -p ~/data

然后在终端中输入命令安装Samba

sudo apt update && sudo apt install samba

配置Samba服务

1、在终端中,使用以下命令备份默认的Samba配置文件:

sudo cp /etc/samba/smb.conf /etc/samba/smb.conf.bak

2、在终端中,使用以下命令创建一个Samba用户:

sudo smbpasswd -a username

将username替换为您要创建的用户名,并按照提示设置密码。

3、使用文本编辑器(如Nano、vim)打开Samba配置文件:

sudo vim /etc/samba/smb.conf

4、在配置文件的底部添加以下内容来创建共享文件夹:

[data]
   comment = Shared Folder
   path = /home/node1/data
   browseable = yes
   writable = yes
   guest ok = no
   available = yes
   create mask = 0777
   directory mask = 0777
   force user = deepl
   force group = deepl

创建Samba用户

  • 增加samba用户提示Failed to add entry for user
[root@ubuntu ~]# smbpasswd -a test
New SMB password:
Retype new SMB password:
Failed to add entry for user test.

解决办法:
这是因为没有加相应的系统账号,所以会提示Failed to add entry for user的错误,只需增加相应的系统账号test就可以了:

[root@ubuntu ~]# groupadd test -g 6000
[root@ubuntu ~]# useradd test -u 6000 -g 6000 -s /sbin/nologin -d /dev/null

重启Samba服务

1、在终端中,使用以下命令重启Samba服务:
sudo service smbd restart

访问共享文件夹

在windows的文件资源管理器中添加网络映射位置就可以了

安装Cockpit管理界面(在有idrac时可以不装)

Cockpit是一个服务器管理器,可以通过Web浏览器轻松管理GNU / Linux服务器。 它使Linux变得可发现,从而使系统管理员可以轻松地执行任务,例如启动容器,存储管理,网络配置,检查日志等。

sudo apt-get install -y cockpit # 安装
sudo systemctl start cockpit.socket # 启动cockpit
sudo systemctl enable cockpit.socket # 自启动cockpit

启动Cockpit服务后,它将开始在端口9090上侦听。打开浏览器并将其导航到以下URL。

https://ip-address:9090

创建一个新的普通用户(可选)

  • 创建了可以登录的User01用户并使用/bin/bash作为shell。
  • 设置密码。
  • 为User01用户增加管理员权限。
  • 切换登录用户为User01。
$ sudo useradd -m user1 -s /bin/bash
$ sudo passwd user1
$ sudo adduser user1 sudo
$ su user1

配置Docker及Nvidia-Container-Toolkit

通常实验室会有多人使用服务器,为此我们需要服务器能给每个用户分配一个干净的运行环境。

主流的工具是conda、virtual env以及docker。相比较于前两者主要用来隔离python不同版本的虚拟环境;有时候我们的开发环境并不只是用到python,比如有的native库需要对应gcc版本的编译环境,或者进行交叉编译时会安装很多工具链等等。如果这些操作都在服务器本地上进行,那时间久了就会让服务器的文件系统非常杂乱,而且还会遇到各种软件版本冲突问题。这时候docker就可以发挥用场了,只需要在本机安装显卡驱动,其他的操作在docker镜像里。

安装Nvidia显卡驱动

禁用secure boot

Dell服务器在bios中可以关闭

禁用nouveau

打开终端,输入:

sudo vi /etc/modprobe.d/blacklist.conf

在blacklist.conf文件末尾加上这两行,并保存:

blacklist nouveau

options nouveau modeset=0

然后执行命令:

sudo update-initramfs -u  //应用更改

安装驱动

这里我们通过命令行安装,输入ubuntu-drivers devices查看当前机器支持的驱动,选择recommended那项执行安装,例如:

sudo apt install nvidia-driver-470

使用–without-recommends可以只安装需要的东西,节省空间。

结束后,输入nvidia-smi即可查看显卡信息

  • ls /dev/nvidia*命令,需要看见/dev/nvidia-uvm才行

安装docker和nvidia-container-toolkit

为了在docker中支持GPU,NVidia之前是弄了个nvidia-docker2,现在升级为NVIDIA Container Toolkit了。

配置Docker

# 更新源
sudo apt update

# 启用HTTPS
sudo apt install -y \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common

# 添加GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

# 添加稳定版的源
sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"

安装Docker CE

# 更新源
sudo apt update

# 安装Docker CE
sudo apt install -y docker-ce

配置镜像加速器

#镜像加速器可以个人去阿里云注册申请
sudo mkdir -p /etc/docker
#配置加速器地址  镜像加速器可以自己注册
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://XXXXXXX.mirror.aliyuncs.com"]  
}
EOF

#重启守护进程
sudo systemctl daemon-reload
#重启docker服务
sudo systemctl restart docker

添加到Docker组

#创建Docker组
sudo groupadd docker

# 添加用户到Docker组
sudo usermod -aG docker 用户名

#查看是否添加成功
cat /etc/group | grep ^docker

#重启docker
sudo systemctl restart docker

#更新用户组
newgrp docker

#添加完成后,操作docker命令不再需要sudo权限

更改Docker镜像保存地址(2023-10-4新增)

docker镜像默认保存在 /var文件夹中。如果根目录空间不够,可以考虑迁移到其他的磁盘中。

  • 新建Docker镜像路径
sudo mkdir -p /home/${USER}/docker/
  • 停止Docker服务
sudo systemctl stop docker

# 查看docker服务状态
sudo systemctl status docker
  • 修改Docker的daemon.json文件
# 修改配置文件
vim /etc/docker/daemon.json

# 在配置文件中加入新的要保存的路径地址
{

    "data-root": "/new-path/docker"
}
  • 重启Docker服务
# 重新reload配置文件
sudo systemctl daemon-reload

# 重启docker服务
sudo systemctl start docker
  • 检查修改后的路径是否正确

# 输入docker info 查看data-root的路径是否正确
docker info

测试Docker CE

$ sudo docker run --rm hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
b8dfde127a29: Pull complete 
Digest: sha256:9f6ad537c5132bcce57f7a0a20e317228d382c3cd61edae14650eec68b2b345c
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

若出现以上信息,则安装成功,祝好运!

配置Nvidia-container-toolkit

# 添加源
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list

# 安装并重启docker
sudo apt update && sudo apt install -y nvidia-container-toolkit
sudo systemctl restart docker

在安装步骤,很容易因为国内网络而失败。因此提供另一种方法

# 添加源
$ distribution="ubuntu18.04"
$ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
$ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list

# 更新
sudo apt update

# 进入下面链接,并下载最新版的“libnvidia-container1”
# 举例:libnvidia-container1_1.X.0-1_amd64.deb
https://github.com/NVIDIA/libnvidia-container/tree/gh-pages/stable/ubuntu18.04/amd64

# 使用dpkg进行安装
sudo dpkg -i libnvidia-container1_1.X.0-1_amd64.deb

# 重复nvidia-container-toolkit安装,大概率能够完成安装
sudo apt install -y nvidia-container-toolkit

# 重启docker
sudo systemctl restart docker

测试nvidia-container-toolkit

# 在官方CUDA镜像上测试 nvidia-smi
$ sudo docker run --gpus all --rm nvidia/cuda:11.0-base nvidia-smi

# 启动支持双GPU的容器
$ sudo docker run --gpus 2 --rm nvidia/cuda:11.0-base nvidia-smi

# 指定指定GPU 0,1,运行容器
$ sudo docker run --gpus device='"0,1"' --rm nvidia/cuda:11.0-base nvidia-smi

若出现GPU信息,则代表成功,如下图:

解决容器内中文乱码问题

打开bash/bashrc

vi /etc/bash.bashrc

添加:

export LC_ALL="C.UTF-8"

然后:

source /etc/bash.bashrc
容器内时间区域问题

挂载/etc/localtime

docker cp /etc/localtime: 容器名 /etc/localtime

date #查询当前时间

Docker常用命令

#容器生命周期管理
docker [run|start|stop|restart|kill|rm|pause|unpause|create]

#容器操作运维
 docker [ps|exec|inspect|top|attach|events|logs|wait|export|import|port]

#容器rootfs命令
 docker [commit|cp|diff]

#本地镜像管理
 docker [images|rmi|tag|build|history|save]

#镜像仓库
 docker [login|pull|push|search]

#其他命令
 docker [info|version]

详细命令说明如下:

#在后台启动一个容器
docker run -d --name alias-Name imageName

#启动容器
docker start Name/ID

#停止容器
docker stop Name/ID

#重启容器
docker restart Name/ID

#杀死一个运行的容器
docker kill -s KILL Name/ID

#删除容器
docker rm /rm -f Name/ID

#停止容器
docker pause Name/ID

#恢复容器
docker unpause Name/ID

#只创建容器但不启动
docker create --name CONTAINER_Name imageName

#查看运行的容器
docker ps / docker ps -a

#进行一个运行中的容器,开启一个新的终端
docker exec -it CONTAINER_ID /bin/bash

#进行一个运行中的容器,不开启一个新的终端
docker attach CONTAINER_ID

#查看容器的相关信息
docker inspect CONTAINER_Name

#查看容器里面的进程
docker top CONTAINER_Name

#时间戳=2016年7月1日后的相关事件
docker events -f "image"="imageName" --since="1467302400"

#查看容器的日志输出
docker logs CONTAINER_Name

#阻塞运行直到容器停止,然后打印出它的退出代码
docker wait CONTAINER_Name

#将容器进行打包保存到本地,文件类型为tar
docker export -o test.tar CONTAINER_ID

#将上面保存的文件导入到镜像库中
cat test.tar |docker import - image_name:tag

#查看容器的端口映射情况
docker port CONTAINER_ID

#commit 从容器中创建一个新的镜像
docker commit -a "tony test" -m "my mysql" CONTAINER_ID mymysql:v1
docker images mymysql:v1

#cp 在使用的过程中会进行多个主机与容器之间的数据交换
docker cp /ruiqi/content CONTAINER_ID:/ruiqi/

#diff 用来检查容器里面文件结构的更改
docker diff CONTAINER_ID

#查看本地的镜像,-a 表示是所有的镜像
docker images /docker images -a

#删除镜像
docker rmi -f image_name

#给镜像做一个有别名的复本
docker tag mysql:v5.6 mysql:v5.7

#构建一个镜像
docker build -t runoob/ubuntu:v1 .

#查看当前这个镜像的历史信息
docker history image_name

#将当前的镜像保存到本地的一个tar 类型的文件
docker save -o TestFlask.tar TestFlask:v3

#登录镜像仓库
docker login

#从镜像仓库中拉镜像
docker pull

#向镜像仓库推本地的镜像文件
docker push

#检索镜像内容
docker search

Portainer容器管理界面搭建

Portainer 是一款轻量级的应用,它提供了图形化界面,用于方便地管理Docker环境,包括单机环境和集群环境。

最新版Portainer能够对GPU数量、计算用途进行设定。为降低Docker容器设置的学习成本,采用Portainer建立个人开发环境。

# 拉取Portainer社区版的最新镜像
docker pull portainer/portainer-ce:2.16.2

# 部署Portainer
docker run -d -p 8000:8000 -p 9000:9443 \
			--name=portainer --restart=always \
			-v /var/run/docker.sock:/var/run/docker.sock \
			-v portainer_data:/data \
			portainer/portainer-ce:2.16.2

搭建完成后,在浏览器中输入:https://IP:9000,就能进入管理界面。

初次进入需要设置密码。

在使用过程中,我们需要设置用户组,对训练环境进行管理。

网络登录浏览器搭建

校园网对学生个人上网有设备上限,因此服务器联网时可能会因个人账号在不同设备登录而被挤下线。但是学校对实验室自建WIFI没有限制,因此一个账号登录WIFI后能够满足多人使用。之前方案是通过路由器的虚拟服务器进行端口转发,这种方案会导致服务器设置的samba文件夹无法被使用网线上网的同学访问。为了解决这种问题,搭建一个Web浏览器来实现上网登录。

docker run -d \
  --name=firefox \
  --security-opt seccomp=unconfined `#optional` \
  -e PUID=1000 \
  -e PGID=1000 \
  -e TZ=ASIA/Shanghai \
  -p 3000:3000 \
  -p 3001:3001 \
  -v /home/user1/firefox-config:/config \
  --shm-size="1gb" \
  --restart unless-stopped \
  lscr.io/linuxserver/firefox:latest

参数说明

参数

功能

-p 3000

Firefox UI界面

-e PUID=1000

UserID - 下方详解

-e PGID=1000

GroupID - 下方详解

-e TZ= ASIA/Shanghai

指定时区 ASIA/Shanghai

-v /config

容器内文件挂载到宿主机

--shm-size=

这是任何现代网站像YouTube一样运作所必需的。

--security-opt seccomp=unconfined

仅对于 Docker 引擎,许多现代 gui 应用程序需要它才能在较旧的主机上运行,因为 Docker 不知道系统调用。

用户/组标识符

使用卷(标志)时,主机操作系统和容器之间可能会出现权限问题,我们通过允许您指定用户和组来避免此问题。

- v PUID PGID

确保主机上的任何卷目录都归您指定的同一用户所有,并且任何权限问题都将像魔术一样消失。

在本例中,要找到您的用途,如下所示:PUID=1000 PGID=1000 id user

$ id username     
  uid=1000(dockeruser) gid=1000(dockergroup) groups=1000(dockergroup)
解决Web页面中文乱码问题

如果没有安装中文字体,在界面时会出现中文不显示的问题

对于容器已存在时,可以将中文字体(C:\Windows\Fonts\微软雅黑\msyh.ttc)拷贝到容器/usr/share/fonts/目录下,也能解决中文乱码

$ docker cp msyh.ttc Container_name_or_ID:/usr/share/fonts/
解决浏览器状态栏中文乱码问题(同容器内中文乱码问题)

打开bash/bashrc

vi /etc/bash/bashrc

添加:

export LC_ALL="C.UTF-8"

然后:

source /etc/bash/bashrc

FileBrower搭建(可选)

FileBrowser是一款配置要求低、运行速度快、页面友好的个人网盘和网页版文件管理器

FileBrower用来替换命令行的文件上下传。

规定所有工程文件上传到指定文件夹中

# 创建filebrowser挂载所需要的目录
mkdir filebrowser

# 启动filebrowser
docker run \
    -v /path/to/:/srv \
    -v /path/to/filebrowser.db:/database/filebrowser.db \
    -v /path/to/settings.json:/config/settings.json \
    -e PUID=$(id -u) \
    -e PGID=$(id -g) \
    -p 8080:80 \
    filebrowser/filebrowser

默认账户:admin

默认密码:admin

FileBrower创建成功后,可以打开用户注册选项,确保工程文件空间独立。

深度学习容器创建与配置

终端容器创建(示例)

这里推荐使用deepo这样一款中国人做出来的深度学习镜像,包含了现在多数流行的深度学习框架。

在下载好deepo镜像后,输入以下命令创建一个容器:

docker run -it --gpus all \
    --ipc=host \
    -p 8889:8888 \
    -p 8022:22 \
    -v /path/to/workspace:/workspace \
    --name rongqi_1 \
    --label io.portainer.accesscontrol.teams=XXX \
    ufoym/deepo:all-jupyter-py36-cu111 /bin/bash
  • -it:进入交互模式,启动bash
  • --gpus all:宿主机全部GPU可供容器使用
  • --ipc=host:容器共享宿主机内存
  • -p 8889:8888 -p 8022:22 :端口映射,主要是两个目的:
    • 通常我们需要安装jupyter notebook进行处理,其默认为容器的8888端口,将它映射到宿主机8889端口,
    • 将ssh服务的22端口映射到宿主机的8022端口,之后可通过vscode访问到服务器上运行的镜像环境
  • --label io.portainer.accesscontrol.teams=sci:将容器管理权限赋给sci用户组
  • -v /path/to/workspace:/workspace:深度学习框架的docker镜像都默认带有/workspace目录,可实现和宿主机的指定目录(这里规定将文件挂载在Share文件夹下)进行文件共享
  • --name:对容器命名

设置以root账户ssh连接

  • 设置 root 账户密码:
passwd root
  • 很多镜像都不会默认安装 ssh,所以需要在容器内安装 ssh 服务:
apt update && apt install -y openssh-server
  • 一般进入容器时使用的都是 root 账号,但是 ssh 默认是禁止 root 账号使用密码远程登录的,所以需要修改 ssh 配置文件使其允许:
vim /etc/ssh/sshd_config 

# 修改如下两处地方,
将 Port 22 前面的注释去掉(开启22号端口)

允许root用户以任何认证方式登录(用户名密码认证和公钥认证)
#PermitRootLogin without-password 改为 PermitRootLogin yes
#PasswordAuthentication yes 改为 PasswordAuthentication yes

需要注意的是由于ssh配置文件的权限是只读,vim编辑后,退出时需要输入:wq!强制保存更改

编辑完后确认ssh-server是否启动了:ps -e | grep ssh。 如果没有可执行service ssh start

配置SSH服务随容器启动
#由于docker中没有systemctl权限,所以我们采取脚本方式启动ssh服务
1.在 /root 目录下新建一个 start_ssh.sh文件,并给予该文件可执行权限:

touch /root/start_ssh.sh
vim /root/start_ssh.sh
chmod +x /root/start_ssh.sh

2.start_ssh.sh 脚本的内容,如下:

#!/bin/bash
LOGTIME=$(date “+%Y-%m-%d %H:%M:%S”)
echo “[$LOGTIME] startup run…” >>/root/start_ssh.log
service ssh start >>/root/start_ssh.log
#service mysql start >>/root/star_mysql.log   //其他服务也可这么实现

5.将start_ssh.sh脚本添加到启动文件中

vim /root/.bashrc

6.在 .bashrc 文件末尾加入如下内容:

if [ -f /root/start_ssh.sh ]; then
      ./root/start_ssh.sh
fi

7.保存后,等下次重启容器的时候,添加的服务也就跟着重启了。

配置jupyterlab(可选)

插件支持

jupyter lab支持许多插件,一般需要安装node.js才能使用:

# 安装nod.js 14.x版本
curl -fsSL https://deb.nodesource.com/setup_14.x | bash -
apt-get install -y nodejs
设置jupyter登录密码
# 生成配置文件
jupyter lab --generate-config

# 进入python或ipython,设置密码,并记录
from notebook.auth import passwd
passwd()

#保存生成的密钥
修改配置文件

vim /root/.jupyter/jupyter_lab_config.py

# 添加内容如下:
c.NotebookApp.password = "XXXX"  #保存的密钥复制到这个位置
c.NotebookApp.ip='0.0.0.0'	# *允许任何ip访问
c.NotebookApp.open_browser = False	# 默认不打开浏览器
c.NotebookApp.allow_remote_access = True
c.NotebookApp.notebook_dir = '/mnt/hhd' # 修改为之前设置于宿主机共享的路径

在容器内启动:jupyter lab --allow-root,然后在服务器的浏览器里打开映射端口:服务器ip:8889 输入密码就能访问。

正常退出不关闭容器,请按Ctrl+P+Q

IDE远程开发

通过Vscode实现远程开发

使用 VSCode 连接,添加新的 ssh host 的时候地址这么写:ssh root@your-server-ip -p 8022,这个 8022 就是启动容器的时候设置的映射端口。之后输入root账户密码即可,和正常的连接远程服务器一样。

连接到容器后,输入jupyter lab --allow-root启动容器内的jupyter,在VsCode终端设置端口转发规则,即可把jupyter默认端口转发到本地指定端口打开。

Zerotier One搭建

Zerotier介绍

概念

所有的设备都是客户端,连接方式是点对点。在路由器下面的话是用 uPnP 的方式进行转发实现客户端到客户端的直接连接。如果 uPnP 没有开启,会通过传统的服务器转发的方式进行连接。

Earth

根据其介绍,将地球上的所有设备连起来。那这里的 Earth 指的就是整体的一个服务。

Network

每一个 Network 包含的所有设备都在同一个网络里。每个网络有一个 Network ID。各客户端通过这个 ID 连接到此网络。当然,一个账号是可以创建多个网络的。

网络氛围 Public 和 Private。一般我们自己组网是要用 Private,需要在页面授权设备才可以进行访问。Public 权限好像不太有人会需要吧..

以下介绍的所有概念都是属于 Network 下的。

Planet

星球嘛。指的是官方提供的服务器节点。各客户端都是通过这些服务来互相寻址的。相当于 zookeeper 的不同节点。

Moon

自定义的 Planet。由于 Zerotier 没有国内节点,在两个设备刚开始互连的时候有可能需要通过国外的节点寻址(不过我没发现有什么慢的)导致创建连接的速度偏慢。在自己的网络里搭建 Moon 可以使连接提速。

Leaf

客户端。就是连接到网络上的每一个设备。其实经过测试,Moon 也是客户端的一种。这里特指没有额外功能,单纯用于连接的客户端。

Zerotier One 安装

# 直接下载
# 需先安装curl
curl -s https://install.zerotier.com | sudo bash

# ubuntu下建议用这种方便用apt管理
curl -s 'https://raw.githubusercontent.com/zerotier/ZeroTierOne/master/doc/contact%40zerotier.com.gpg' | gpg --import && \
if z=$(curl -s 'https://install.zerotier.com/' | gpg); then echo "$z" | sudo bash; fi

sudo apt install zerotier-one -y

下载成功后会出现类似35ho0d88g73的Address id,需要记住它(后续也可通过zerotier-cli info或zerotier-cli status查看);若未出现请重复上一流程

在ZerTier官网上双击在第二步创建网络,下翻找到MANUALLY ADD MEMBER填入第四步的Address并确认

加入、离开、列出网络(<NETWORK ID>就是第二步创建好的网络标识)

zerotier-cli join <NETWORK ID>
#加入
zerotier-cli leave <NETWORK ID>
#离开
zerotier-cli listnetworks
#连接列表

启停

sudo systemctl start zerotier-one.service
#启动
sudo systemctl stop zerotier-one.service
#停止
systemctl enable zerotier-one.service
#打开开机自启
systemctl disable zerotier-one.service
#关闭开机自启

搭建Zerotier One Moon转发服务器

先决条件建议:有一台云服务器,很多童鞋说要钱,刚刚白piao了一百度云的服务器,一年只要38RMB,配置CentOS7.9-1C1G1M带宽(moon模式服务器只是做转发所以不用担心),至于怎么piao就是新用户福利,能够搞2台。这里就不赘述,不懂可以留言。(zerotier搭建moon模式-CSDN博客

一、安装zerotier客户端到云服务器

curl -s https://install.zerotier.com | sudo bash

二、加入自己的NETWORK ID(之前有介绍过怎么加入可以看我前面的文章)

ZeroTier内网穿透工具配置_zetion_3的博客-CSDN博客_zerotier 配置

zerotier-cli join xxxxxxxx

加入后记得去zerotier勾选主机让主机能有权限连接进你的内网

三、配置moon(重点来了)

进入zerotier-one安装目录默认是/var/lib/zerotier-one

cd /var/lib/zerotier-one

生成 moon.json 配置文件

zerotier-idtool initmoon identity.public >> moon.json

编辑 moon.json 配置文件

vim moon.json

将配置文件中的 "stableEndpoints": [] 修改成 "stableEndpoints": ["ServerIP/9993"],将 ServerIP 替换成云服务器的公网IP。红色为重点切记是公网IP/9993这里是斜杠/里面用引号引起来。

创建moon文件

zerotier-idtool genmoon moon.json

新建moons.d文件将生成的000*****.moon文件移动进去

mkdir moons.d
mv 000000xxxxxxxxxx.moon moons.d

重启 zerotier-one 服务

systemctl restart zerotier-one

自此moon就搭建好了,接下来就是客户端应用了。

四、 Linux客户端加入moon

通过以下命令查找当前你网络内的主机信息

zerotier-cli listpeers

通过下面的命令加入moon的节点名节点名就是listpeers命令输出后的第三列(2次)

zerotier-cli orbit ******** *******

再运行一下就变moon模式了

五、windows客户端加入moon

以管理员身份打开 PowerShell,将命令中的两组 xxxxxxxxxx 都替换成 moon 的节点ID。

C:\Windows\system32> zerotier-cli.bat orbit xxxxxxxxxx xxxxxxxxxx

检查是否添加成功

C:\Windows\system32> zerotier-cli.bat listpeers

附录

关于容器内可视化界面的设置

有两种方案,一种是基于VNC的web端显示,另一种是通过Nomachine实现桌面化。

因为VNC方案不支持GPU硬件加速的3D渲染,这样就无法运行像Gazebo这样的3D软件,就算支持,也是基于软件模拟的OpenGL,占用大量的CPU。

因此采用Nomachine+docker方案。

具体实施参考:基于Docker的GPU服务器桌面虚拟化 - gezp的文章 - 知乎

宿主机启用nomachine屏幕分辨率低的问题

默认远程桌面是使用显示器的分辨率,由于无显示器连接远程桌面,导致默认分辨率低。一行命令解决:

xrandr --fd 1280x720 

但是分辨率不可过高,分辨率越高延迟越大。

  • 19
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用Docker容器搭建socket服务器可以方便地进行部署和管理。下面是一个简单的步骤: 1.编写Dockerfile文件 首先需要编写一个Dockerfile文件,指定要使用的镜像、安装必要的软件和配置环境变量等,例如: ``` FROM python:3.7-alpine WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY . . CMD ["python", "server.py"] ``` 2.编写socket服务器代码 编写socket服务器代码,例如: ``` import socket HOST = '0.0.0.0' PORT = 8080 with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind((HOST, PORT)) s.listen() conn, addr = s.accept() with conn: print('Connected by', addr) while True: data = conn.recv(1024) if not data: break conn.sendall(data) ``` 3.构建Docker镜像 在Dockerfile所在目录执行以下命令来构建Docker镜像: ``` docker build -t my-socket-server . ``` 其中,my-socket-server是镜像名称,可以自定义。 4.运行Docker容器 使用以下命令来运行Docker容器: ``` docker run -p 8080:8080 my-socket-server ``` 其中,8080是容器内部端口,也是socket服务器监听的端口,可以自定义;8080是宿主机端口,用于访问socket服务器。 5.测试socket服务器 使用telnet或其他工具来测试socket服务器,例如: ``` telnet localhost 8080 ``` 输入任意字符并回车,可以看到服务器返回该字符。 以上就是使用Docker容器搭建socket服务器的基本步骤,可以根据实际需求进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值