服务器上docker创建及qemu环境搭建
1. 需要准备的软件
1.1 VS Code
这个软件无需多言,值得一提的是,VS Code只是一个高级的编辑器,而非一个编译器,下载好之后其自身是不带任何编译和调试功能的,如果想在本机上开发c/c++项目,还需要安装Mingw-w64,理解成gcc的windows版本即可,这样就可以愉快的在本地上进行c/c++的开发了。但下载VS Code的主要目的是连接远程的服务器,直接在服务器上开发,而服务器本身是有gcc的,所以如果后续没有需要本地开发的项目,下载好VS Code之后就不需要再安装Mingw-w64了
1.2 Filezilla
这个软件使用起来很简单,主要作用是可以远程连接主机,实现本地和远程主机之间的文件上传和下载,虽然在命令行中也可以实现,但我还是喜欢这种有UI界面的实现方式
连接后就可以看到服务器和你操作的电脑的目录,可以在主机和服务器之间上传下载文件
1.3 ATrust
因为学校服务器需要连接北邮校园网才可以使用,所以如果电脑不在学校,就需要使用vpn来连接
1.4 Clash Verge
这个无需多言,自己捣鼓
1.5 MobaXterm
这是一款有很多功能的软件,主要用vnc连接后续的容器,所以也可以使用其他的vnc软件,比如RealVnc Viewer
2 . 连接服务器
2.1 申请服务器账号
因为此项目需要套三层虚拟机,所以建议在服务器上运行,如果电脑配置足够高,也可以在本机电脑上运行。
2.2 连接服务器
2.2.1 安装SSH服务插件
在vscode的扩展里,搜索remote-ssh扩展然后安装
2.2.2 连接服务器
在搜索栏里输入命令
>ssh juze.han@10.112.105.34
其中,juze.han
是申请的服务器的账号名,10.112.105.34
是服务器ip,值得注意的是,如果在校外,需要使用atrust连接北邮vpn才能连上,并且vscode最好使用管理员权限启动,如果不用管理员权限,我的vscode会提示ssh.exe被拒绝访问。
在进入服务器后,ls
查看目录
要注意自己在服务器上的权限并非root,所以无法执行sudo系列命令
3 配置docker环境
3.1 docker理解
关于docker,理解为一个轻量化的虚拟机就可以,具有很好的移植性。配置一个Docker的流程就是三步,编写Dockerfile
,生成doker镜像文件
,根据镜像文件生成具体的容器
。Dockerfile,Dockerimg(docker镜像),DockerContainer(容器),三者关系是递进的,镜像文件是根据Dockerfile生成的,容器是根据镜像文件生成的。一个dockerfile可以生成一个镜像文件,一个镜像文件在启动时输入不同的命令可以生成多个容器
3.2 Dockerfile
连接服务器后,创建一个Dockerfile
文件夹,进入此文件夹,在vscode终端里输入
code dockerfile
此时会生成Dockerfile
文件,在文件里填写如下内容
FROM ubuntu:24.04 # 定义构建时变量,可以在docker build构建通过--build-arg来修改 ARG GID=1005 ARG UID=1004 ARG username=hjz # 设置 DEBIAN_FRONTEND 环境变量以避免交互式对话框,否则可能会卡在一些交互式输入中 ENV DEBIAN_FRONTEND=noninteractive # 修改ubuntu的镜像源为阿里云 # ubuntu24.04版本修改软件源的位置:/etc/apt/sources.list 替换为 /etc/apt/sources.list.d/ubuntu.sources RUN sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list.d/ubuntu.sources \ && sed -i s@/security.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list.d/ubuntu.sources \ && apt-get update -y && apt-get install -y sudo locales \ && apt-get clean \ && echo "%sudo ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers # 修改容器或系统中的 sudoers 文件,允许属于 sudo 组的用户执行 sudo 命令时无需输入密码。 # 修改语言环境(locale)设置 RUN locale-gen en_US.UTF-8 && update-locale # 注:用户id和组id尽可能的和当前用户id一致,使得读写共享文件时的权限一致,否则可能出现docker无法写入共享文件的问题。 # 命令 id 可以查看用户的各种id RUN getent group ${GID} || groupadd -g ${GID} dev \ && getent passwd ${username} || useradd -ms /bin/bash -u ${UID} -g ${GID} -G sudo ${username} \ && echo "${username}:012515" | chpasswd \ && echo 'root:012515' | chpasswd # 添加用户:赋予sudo权限,指定密码012515,建议docker的密码不要太复杂,太多了很容易忘记。 # 安装各种以依赖软件,可以根据需要定制,也可以后续手动安装。 # QEMU编译需要的依赖 RUN apt-get update && apt-get install -y build-essential meson ninja-build pkg-config \ diffutils python3 python3-venv \ libglib2.0-dev libusb-1.0-0-dev libncursesw5-dev \ libpixman-1-dev libepoxy-dev libv4l-dev libpng-dev \ libsdl2-dev libsdl2-image-dev libgtk-3-dev libgdk-pixbuf2.0-dev \ libasound2-dev libpulse-dev \ libx11-dev libfdt-dev libiscsi-dev # # riscv-gnu-toolchain 需要的依赖 # RUN apt-get install -y autoconf automake autotools-dev curl \ # python3 python3-pip libmpc-dev libmpfr-dev libgmp-dev gawk build-essential \ # bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev \ # ninja-build git cmake libglib2.0-dev libslirp-dev # RUN apt-get install -y git gdb clang cmake vim gdb # 还原 DEBIAN_FRONTEND 环境变量(可选) ENV DEBIAN_FRONTEND=dialog # 指定容器启动后的工作目录 WORKDIR /home/${username} # 指定容器启动后的登录用户 USER ${username}
具体内容可以自行搜索并更改,输入后保存即可。
其中linux的发行版本和版本号可以更换,GID
和UID
需要改为自己在服务器中的id,可以使用id命令查看
username
是容器中的用户,可以随意指定
注意:存放 Dockerfile
的文件夹中最好不要存放任何其他无关的文件,在创建镜像时,docker 会将该文件夹中的所有内容都复制到容器中,这会大大增加镜像创建的时间
3.3 docker镜像
在dockerfile所在文件夹下运行如下命令
docker build -t hjz-qemu .
其中 -t
后跟镜像名称,可任意更改。docker build -t hjz-qemu .
这条命令会从当前目录(.
)中寻找 Dockerfile
,然后根据其中的指令构建一个名为 hjz-qemu
的 Docker 镜像。
3.4 创建容器
使用如下命令根据上边创建的镜像来生成一个容器
docker run -it --network host --name hjz-qemu-con --mount type=bind,source=/home/juze.han/work/,target=/home/hjz/work --device /dev/kvm hjz-qemu
# --network host 使创建的容器处于host模式(容器与宿主机共享网络,容器的所有端口都会直接暴露在宿主机的端口上,可以设置为其他的网络模式,自行搜索) # --name hjz-qemu-con 创建一个名为 hjz-qemu-con 的容器 # --mount type=bind,source=/home/juze.han/work/,target=/home/hjz/work 将主机的文件夹 /home/juze.han/work共享(挂载)到容器中的 /home/hjz/work 文件夹 # type=bind 表示挂载类型是绑定挂载容器对挂载的目录拥有完全的读写权限,容器内删除了文件,宿主机的文件也会删除,因此要小心操作,如果不想同步,可以使用copy指令,自行搜索 # --device /dev/kvm 表示容器可以直接访问主机/dev/kvm # hjz-qemu 表示是使用hjz-qemu这个镜像创建的容器
执行完后就会生成一个docker容器了,容器内运行的是dockerfile里指定的系统,对我来说就是24.04版本的Ubuntu。在创建容器后,就无法再对容器的权限做更改了,想要修改容器的权限或者其他属性,就得用docker镜像重新生成一个容器,在生成容器的命令中对容器的属性进行增删改。如果不想重新在新容器里配置环境,也有可以保存当前容器状态并继承到新容器的方法,自行搜索。
3.5 连接容器
在vscode里下载dev containers
扩展插件,就可以使用vscode连接自己创建的容器了,可以直接在vscode操作容器
4. Qemu源码编译
首先明确一下环境配置的顺序,qemu本身是可以模拟cpu,网卡等硬件设备的,而linux本身就是一个操作系统,linux与qemu可以模拟一个完整的计算机。目标是在qemu内运行linux,而qemu本身要运行在linux下,所以就是linux下运行qemu,qemu内再运行linux。虽然服务器本身就是linux环境,但由于是与其他同学共用,且没有root权限,所以对linux内核方面是没有操作权限的,为了获得root权限,就在服务器上生成一个属于自己的docker容器,容器内也是linux环境,并且自己在容器内是有root权限的。因此,在成功生成docker容器后,我们就可以在容器内运行qemu,然后再用qemu运行linux。本节所有操作都是在容器内进行的
4.1 目录结构
为了方便理解,贴上我服务器与容器内的目录结构
4.2 下载qemu源码
采用的是从源码编译qemu的方法,这样就可以自己进行需要的功能的配置。
首先要安装编译qemu源码需要的依赖
sudo apt -y install clang ninja-build build-essential zlib1g-dev pkg-config libglib2.0-dev binutils-dev libpixman-1-dev libfdt-dev
这一步其实有点多余,因为在Dockerfile
文件里,已经写了qemu编译所需要的依赖了,但我在运行的时候不知道为什么,容器内确实没有安装,所以我又重新安装了一下,如果确定已经安装,这一步可以跳过
然后从官网下载qemu源码,最好将源码单独放一个文件夹内,如果网络不通畅,要么用vpn,要么用百度网盘从别人那下载好后,使用filezilla上传到服务器的work文件夹下存放qemu源码的文件夹(对我来说就是~/work/qemu-9.0.0
),然后就会自动同步到容器内的work文件夹了
wget https://download.qemu.org/qemu-9.0.0.tar.xz
4.3 解压
下载后的源码是压缩包,需要解压
xz -d qemu-9.0.0.tar.xz tar xvf qemu-9.0.0.tar
4.4 编译
进去qemu源码目录(~/work/qemu-9.0.9
)后,新建build文件夹,用来存放编译后的文件
这里仅编译系统模式下的x86_64模拟器和aarch模拟器,一个用来跑Ubuntu,另一个在未来用来跑openwrt;启用kvm用于在模拟时加速,启用debug模式用于调试qemu:
../configure --enable-kvm --enable-debug --target-list=x86_64-softmmu,aarch64-softmmu
生成配置文件这一步如果提示python报错,可以重新安装一下python-is-python3
,一般不会报错
sudo apt install python-is-python3
然后就可以直接开始编译
ninja
之后会在build目录下生成所需的三个可执行文件:
-
qemu-system-x86_64
x86_64的模拟器 -
qemu-img
用于生成虚拟磁盘文件,对guest来说就是磁盘 -
qemu-system-aarch64
aarch64的模拟器
5. Qemu中Ubuntu环境搭建
5.1 下载ubuntu镜像
操作路径为~/work/download
wget https://mirrors.tuna.tsinghua.edu.cn/ubuntu-releases/22.04/ubuntu-22.04.4-desktop-amd64.iso
这里安装Ubuntu的desktop版本的系统,虽然server版本的也能用,但配置网络环境的过程过于繁琐,而且server版本启动时需要连接网络读取配置文件,在没有配置好qemu网络时启动非常的慢。
如果下载很慢,可以更换为其他镜像源,但我在下载时不管阿里还是清华都只有几十kb的下载速度,最后我去ubuntu官网下载到我主机上,然后通过filezilla上传到了服务器对应文件夹内
5.2 制作虚拟磁盘
不需要手动制作文件系统,Ubuntu的安装程序会自动的格式化磁盘并创建文件系统的目录,因此仅需要创建一个虚拟磁盘文件即可;
使用qemu自带的工具创建磁盘文件,这里创建一个名为ubuntu.qcow2
的文件,注意文件路径即可
../qemu-9.0.0/build/qemu-img create -f qcow2 ubuntu.qcow2 40G
5.3 安装系统
/home/hjz/work/qemu-9.0.0/build/qemu-system-x86_64 \ -m 2G \ -drive format=qcow2,file=ubuntu.qcow2 \ -cdrom /home/hjz/work/download/ubuntu-22.04.2-desktop-amd64.iso \ -nographic \ -vnc 10.112.105.34:6 \ -enable-kvm
各个参数的作用自行搜索即可,比较简单
安装好后再次启动ubuntu时,可以不再加-cdrom /home/hjz/work/download/ubuntu-22.04.2-desktop-amd64.iso
这条命令,推荐把命令保存到.sh脚本文件,直接运行.sh文件即可启动,不需要再敲一大串命令
注意:脚本.sh文件不能有空行,不能通过注释的方法取消掉命令,需要直接删除一整行
我在启动ubuntu这一步时遇到了报错,如下
报错内容是访问不到服务器上的kvm设备,kvm作用是加速虚拟化
原因是我在构建容器时输入的命令
docker run -it --network host --name hjz-qemu-con --mount type=bind,source=/home/juze.han/work/,target=/home/hjz/work --device /dev/kvm hjz-qemu
没有添加--device /dev/kvm hjz-qemu
这一项,而且我在服务器上也不是kvm组,导致我的容器无法访问kvm设备
有两种方法解决报错,第一是将上述启动ubuntu命令的最后一行-enable-kvm
去掉,这样就可以启动ubuntu了,但后果是启动过程极其漫长,我等了十分钟都没进去。
我采用的第二种办法,就是联系学校服务器管理员将我加入kvm组,然后在容器里sudo su
进入root,再运行上述命令就可以正常启动了。
5.4 vnc连接容器
可以发现,在上一步里有个-nographic
的参数,为了可视化ubuntu,就可以使用vnc软件连接容器,在上一步有个命令-vnc 10.112.105.34:6
,设置好了vnc监听的端口。qemu启动的虚拟机默认会在5900端口上启动一个vnc server,这里的:6并不是指的端口号为6,而是指vnc server的编号,0代表的端口号为5900,1代表5901,以此类推。
然后再VNC软件内输入ip和端口号,即可连接qemu启动的ubuntu
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通