在做软件测试或项目开发时,我们可能经常需要安装一个"纯净"的Linux系统测试环境。如果是在Windows下,我们可以使用虚拟机 vmware 或 virtualbox安装虚拟机来解决,而在Windows下则可以使用 轻量级的虚拟机 docker 来实现了。
本文章将详细介绍如何在 Ubuntu Linux服务器下使用 Docker 再安装一个新的 Ubuntu 开发环境。
1.1 Docker 下载 Ubuntu 镜像
首先,我们可以使用 docker search 命令从 docker市场上查找 ubuntu 的系统镜像。
guowenxue@ubuntu20:~$ sudo docker search ubuntu
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
ubuntu Ubuntu is a Debian-based Linux operating sys… 13942 [OK]
websphere-liberty WebSphere Liberty multi-architecture images … 283 [OK]
ubuntu-upstart DEPRECATED, as is Upstart (find other proces… 112 [OK]
neurodebian NeuroDebian provides neuroscience research s… 88 [OK]
open-liberty Open Liberty multi-architecture images based… 51 [OK]
ubuntu-debootstrap DEPRECATED; use "ubuntu" instead 45 [OK]
ubuntu/nginx Nginx, a high-performance reverse proxy & we… 37
ubuntu/mysql MySQL open source fast, stable, multi-thread… 28
ubuntu/apache2 Apache, a secure & extensible open-source HT… 26
... ...
bitnami/ubuntu-base-buildpack Ubuntu base compilation image 0 [OK]
snyk/ubuntu A base ubuntu image for all broker clients t… 0
rancher/ubuntuconsole 0
接下来,就可以使用 docker pull 命令下载 ubuntu 系统镜像。
guowenxue@ubuntu20:~$ sudo docker pull ubuntu
Using default tag: latest
latest: Pulling from library/ubuntu
4d32b49e2995: Pull complete
Digest: sha256:bea6d19168bbfd6af8d77c2cc3c572114eb5d113e6f422573c93cb605a0e2ffb
Status: Downloaded newer image for ubuntu:latest
docker.io/library/ubuntu:latest
下载完成之后,可以使用 docker images 命令查看当前的系统镜像,每个系统镜像都将有一个镜像ID。
guowenxue@ubuntu20:~$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest ff0fea8310f3 11 days ago 72.8MB
1.2 Docker 启动配置 Ubuntu 镜像
下载好Ubuntu系统镜像后,我们可以使用下面命令来 启动一个容器并运行Ubuntu系统镜像。
guowenxue@ubuntu20:~$ sudo docker run -itd --privileged -p 1022:22 --name ubuntu-test ubuntu /bin/bash -c "/bin/bash"
062d82579d7fcb43e3169871f7a2e558ec2220f10ba33fddfd28b34ad47d043b
该命令的参数说明:
-i interactive,交互式;
-t tty,分配一个伪终端;
-d detach, 在后台运行容器;
-p 1022:22 指定主机端口 1022 与容器端口 22 (SSH端口)连接,如果有多个端口需要绑定可以继续使用 -p 添加,如 -p 1021:21。
--name ubuntu-test 设定容器的名称
--privileged 使用该参数container内的root拥有真正的root权限,这样可以看到很多host上的设备,并且可以执行mount。
ubuntu 是docker中已经支持的镜像
/bin/bash -c ... 是容器启动后执行的命令
其他参数请查看docker帮助.
接下来我们可以使用 docker ps 命令查看其是否成功运行,否则使用 docker ps -a 命令查看是否失败。
guowenxue@ubuntu20:~$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
062d82579d7f ubuntu "/bin/bash -c /bin/b…" 4 seconds ago Up 3 seconds 0.0.0.0:1022->22/tcp, :::1022->22/tcp ubuntu-test
每个容器都会有一个 Container ID ,我们可以使用 docker exec 命令进入到容器中运行的 Ubuntu 系统里去。这里我们使用 uname -a 命令可以查看到,当前Ubuntu系统镜像版本为 Ubuntu 20.04.1 .
guowenxue@ubuntu20:~$ sudo docker exec -it 062d82579d7f /bin/bash
root@062d82579d7f:/# uname -a
Linux 062d82579d7f 5.11.0-41-generic #45~20.04.1-Ubuntu SMP Wed Nov 10 10:20:10 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
root@062d82579d7f:/# ls
bin boot dev etc home lib lib32 lib64 libx32 media mnt opt proc root run sbin srv sys tmp usr var
1.3 Docker 中 Ubuntu 系统配置
此时安装的Ubuntu系统非常小,很多命令或工具都没有安装,接下来我们对其进行配置并安装一些常用的开发工具软件。该系统下默认没有安装 nano 和 vi 编辑器,并且其默认的源上没有 vi 命令,这样我们首先需要安装 nano 命令。
root@062d82579d7f:/# apt update
root@062d82579d7f:/# apt install nano
为加快其下载速度,我们修改其源为国内阿里云的源。需要注意的是,这里的Ubuntu系统镜像版本为 Ubuntu 20.04.1,其代号为 focal。
root@062d82579d7f:/# mv /etc/apt/sources.list /etc/apt/sources.list.orig
root@062d82579d7f:/# nano /etc/apt/sources.list
deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
root@062d82579d7f:/# apt update && apt upgrade
接下来我们可以使用下面命令来安装所有我们开发中所需要的软件:
apt install -y vim gawk wget git diffstat unzip chrpath socat flex sed tree cpio rsync coreutils \
sudo xz-utils locales curl lzop bc parted kpartx xterm jq cvs subversion mercurial openssh-server \
build-essential make gcc g++ automake groff autoconf texinfo asciidoc bison docbook-utils help2man \
texi2html autoconf-archive desktop-file-utils binfmt-support iputils-ping bash-completion kmod \
libegl1-mesa libgl1-mesa-dev libglu1-mesa-dev lib32z1 libssl-dev lib32ncurses-dev libncurses-dev \
libsdl1.2-dev qemu qemu-user-static debootstrap debian-archive-keyring dosfstools debianutils \
mtd-utils python3 python3-pip python-pysqlite2 python3-pexpect python3-git python3-jinja2 net-tools \
u-boot-tools device-tree-compiler gcc-9-aarch64-linux-gnu gcc-9-arm-linux-gnueabihf g++-9-arm-linux-gnueabihf
接下来修改root密码并创建一个新的用户 lingyun ,同时给其添加 sudo 权限。
root@062d82579d7f:/# passwd root
New password:
Retype new password:
passwd: password updated successfully
root@062d82579d7f:/# adduser lingyun
root@062d82579d7f:/# visudo
root ALL=(ALL:ALL) ALL
lingyun ALL=(ALL:ALL) NOPASSWD:ALL
使能 SSH 服务:
root@062d82579d7f:/# /etc/init.d/ssh start
* Starting OpenBSD Secure Shell server sshd
Docker下配置完成之后,我们可以使用 exit 命令退出docker 回到 主机下。
root@062d82579d7f:/# exit
exit
1.4 Docker 容器生成镜像
现在我们在容器中费了九牛二虎之力创建了好一个完整的 Ubuntu 系统镜像,这样我们可以把它导出为一个镜像。这样,今后需要的时候可以直接使用该镜像来启动容器,不需要再重新安装、配置系统了。
首先查看并停止该容器的运行。
guowenxue@ubuntu20:~$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
062d82579d7f ubuntu "/bin/bash -c /bin/b…" About an hour ago Up About an hour 0.0.0.0:1022->22/tcp, :::1022->22/tcp ubuntu-test
guowenxue@ubuntu20:~$ sudo docker stop 062d82579d7f
062d82579d7f
接下来我们可以使用 docker commit 来导出镜像了。
guowenxue@ubuntu20:~$ sudo docker commit 062d82579d7f ubuntu-build:20.04
sha256:1482156228e0c1c0eaed05828796be26449b175241117eb5dfa5f5f7800cc939
guowenxue@ubuntu20:~$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu-build 20.04 1482156228e0 54 seconds ago 2.28GB
ubuntu latest ff0fea8310f3 11 days ago 72.8MB
现在,我们的 docker 中有两个系统镜像了:
-
ubuntu-build 这是我们安装并配置好软件后的系统镜像,其大小为 2.28 GB;
-
ubuntu 这是从 docker 市场上 Pull 的系统镜像,其大小才 72.8MB.
1.5 Docker系统SSH远程登录
Ubuntu系统镜像默认并没有启用 ssh 服务,我们可以使用下面命令在启动容器的时候。接下来我们使用新的镜像再次启动一个新的容器,在这个新的容器中使用新的启动参数 "/etc/init.d/ssh start && /bin/bash" ,让容器启动时自动启动 SSH 服务。
guowenxue@ubuntu20:~$ sudo docker run -itd --privileged -p 1022:22 --name ubuntu-lingyun ubuntu-build:20.04 /bin/bash -c "/etc/init.d/ssh start && /bin/bash"
7aa0bafe1c48c177e22cbf913762ffd80721b01e8c56500c12fa20c378a5e47f
guowenxue@ubuntu20:~$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7aa0bafe1c48 ubuntu-build:20.04 "/bin/bash -c '/etc/…" 11 seconds ago Up 9 seconds 0.0.0.0:1022->22/tcp, :::1022->22/tcp ubuntu-lingyun
现在我们在主机上进入容器中看看,是否正常启动了 SSH 服务。
guowenxue@ubuntu20:~$ sudo docker exec -it 7aa0bafe1c48 /bin/bash
root@7aa0bafe1c48:/# netstat -tlnp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 20/sshd: /usr/sbin/
tcp6 0 0 :::22 :::* LISTEN 20/sshd: /usr/sbin/
root@7aa0bafe1c48:/# exit
exit
guowenxue@ubuntu20:~$
由上可以看出,SSH2协议的 22 号端口被正常监听了,此时我们可以在主机上来测试 SSH2 登录。当然,我们在别的PC上也可以使用 SSH2 协议登录到容器上操作,其中 IP 地址为主机的IP地址,端口号为容器绑定到主机上的端口号 1022。
guowenxue@ubuntu20:~$ ssh -p 1022 lingyun@127.0.0.1
lingyun@127.0.0.1's password:
Welcome to Ubuntu 20.04.4 LTS (GNU/Linux 5.11.0-41-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
This system has been minimized by removing packages and content that are
not required on a system that users do not log into.
To restore this content, you can run the 'unminimize' command.
The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.
lingyun@062d82579d7f:~$ sudo ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet)
RX packets 263720 bytes 756982558 (756.9 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 224310 bytes 12375555 (12.3 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
1.6. Docker删除系统镜像
如果Ubuntu系统镜像不想再用了,可以使用 docker images 命令可以查看当前的 docker 镜像并删除。
guowenxue@ubuntu20:~$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu <none> 54c9d81cbb44 7 weeks ago 72.8MB
每个系统镜像都有个 Image ID,我们可以使用 docker rmi 命令来删除它。如果该镜像有容器正在运行,则会提示出错。
guowenxue@ubuntu20:~$ sudo docker rmi 54c9d81cbb44
Error response from daemon: conflict: unable to delete 54c9d81cbb44 (must be forced) - image is being used by stopped container b5d6400d2f12
使用 docker ps 命令查看该系统镜像确实有容器正在使用。
guowenxue@ubuntu20:~$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b5d6400d2f12 54c9d81cbb44 "bash" 7 weeks ago Exited (0) 3 weeks ago ubuntu
每个容器也有个Container ID,接下来使用 docker 命令停止并删除容器。
guowenxue@ubuntu20:~$ sudo docker stop b5d6400d2f12
b5d6400d2f12
guowenxue@ubuntu20:~$ sudo docker rm b5d6400d2f12
b5d6400d2f12
此时再次使用 docker rmi 命令就可以删除镜像了。
guowenxue@ubuntu20:~$ sudo docker rmi -f ff0fea8310f3
Untagged: ubuntu:latest
Untagged: ubuntu@sha256:bea6d19168bbfd6af8d77c2cc3c572114eb5d113e6f422573c93cb605a0e2ffb
Deleted: sha256:ff0fea8310f3957d9b1e6ba494f3e4b63cb348c76160c6c15578e65995ffaa87
Deleted: sha256:867d0767a47c392f80acb51572851923d6d3e55289828b0cd84a96ba342660c7
guowenxue@ubuntu20:~$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE