如何使用 docker 在 Mac 上运行并配置 Ubuntu
背景#
我校的操作系统课程设计是斯坦福大学的 pintos 项目(当然只需要完成少量的 project)。pintos 需要在 x86 架构的 Linux 系统上运行,但是我最近主力使用的是一台 Macbook Pro,我不太愿意每天背着两台电脑去图书馆。
我原本的设想是把我运行 Ubuntu 机器放在宿舍,通过校园网 ssh 连接到它。但是这样做有两个问题:
- 校园网的网络环境不太好,即使是使用代理也无法保证一些软件源的稳定连接。
- 学校最近在进行消防安全检查,不允许离开宿舍时不断电源,而我没法保证宿舍时刻都有人。
看起来,我只能在 Mac 上跑一个虚拟机了;然而我不太喜欢使用虚拟机的使用体验:在运行时占用太多的内存,启动或者关闭需要等待太长的时间。我希望有一个更轻量的解决方案。
最近,我关注的 up 主 @TheCW 在沉寂了一年之后忽然更新了一个视频。我重新回看了他之前发布的几个视频后,忽然发现他在 Mac 上需要一个 Linux 环境时,直接用 docker run 了一个全新的 Ubuntu 镜像,这个方法看起来非常轻巧——非常适合我。
下文是我在 Mac 上使用 docker 运行 Ubuntu 的步骤。
安装 Docker Desktop for Mac#
访问 Docker 官网 下载 Docker Desktop for Mac 即可,这部分不再赘述。
下载并运行 Ubuntu 镜像#
在终端中输入以下命令来拉取 Ubuntu 镜像:
docker pull --platform linux/amd64 ubuntu
我使用 –platform 来指定镜像的架构,因为我需要一个 x86 架构的镜像;如果直接使用 docker pull ubuntu,docker 会默认自动选择当前机器的架构,这对我来说当然是不行的。
拉取完成后,运行以下命令来启动一个新的 Ubuntu 容器:
docker run --platform linux/amd64 -it ubuntu /bin/bash
这个命令会启动一个新的 Ubuntu 容器,并且进入 bash shell。不过,这个容器还是一个全新的、仅包含最基本软件的 Ubuntu 系统,它看起来应该是这样的:
wood@Woods-MacBook-Pro ~> docker exec -it ubuntu bash
root@8d907eeb-----:/#
如果需要退出容器,使用 exit 命令。
如果要重新进入容器,可以使用 docker ps -a 查看容器的 ID,然后使用 docker start <container-id> 和 docker attach <container-id> 命令。
我们首先应该要新建一个用户,因为 root 用户不应该用于日常操作。在容器中依次以下命令:
apt update
apt install sudo adduser
adduser <your-username>
如果你在 apt update 时遇到了网络问题,可以尝试更换软件源,或者使用代理(参看代理 Docker 容器)。
在按照提示设置密码和其他信息后,我们需要将新建的用户加入 sudo 组:
usermod -aG sudo <your-username>
使用 su 命令切换到新建的用户,并测试一下 sudo 是否正常工作:
su - <your-username>
sudo whoami
如果输出为 root,则说明 sudo 已经正常工作。
Docker 快捷命令#
在继续配置 Ubuntu 容器之前,我想先让启动和退出容器更加方便。
首先使用 docker ps -a 查看容器的 ID,然后使用 docker rename <container-id> ubuntu 命令为容器设置别名为 ubuntu。
随后,我在 ~/.config/fish/config.fish 中添加了以下两个 alias:
alias ubuntu 'docker start ubuntu && docker attach ubuntu'
alias ubuntu-stop 'docker stop ubuntu'
运行 source ~/.config/fish/config.fish 使配置生效。
ps: 如果你使用的是 bash,可以将 alias 添加到 ~/.bashrc 中,并运行 source ~/.bashrc,注意,bash 的 alias 语法和 fish 有所不同,需要使用一个 = 号:alias ubuntu='docker start ubuntu && docker attach ubuntu'。
配置 Ubuntu 容器#
fish shell#
我习惯使用 fish shell,并以 fish 为默认 shell。在容器中,我首先安装了 fish shell:
sudo apt install fish
我没有使用 chsh 命令来更改默认 shell,而是直接修改了对 ubuntu 命令的 alias:
alias ubuntu "docker start ubuntu && \
docker exec -it --user <your-username> \
ubuntu fish -C 'cd ~'"
这样,每次进入容器时,都会以普通用户的身份进入 fish shell,并且进入到用户目录。
到这里,我已经接近了日常使用 Ubuntu 的体验。
screenfetch#
我喜欢登陆时看到 screenfetch,诚实地说,是因为这满足了我小时候对“黑客”的幻想。
我需要在 Docker 容器中安装 screenfetch,然后在 fish 的配置文件中添加 screenfetch 命令。
sudo apt install screenfetch
echo "screenfetch 2>/dev/null" >> ~/.config/fish/config.fish
这里,因为 screenfetch 无法访问宿主机的信息,会显示一行错误信息,所以我在 screenfetch 命令后面加了一个 2>/dev/null 来丢弃错误信息。
我说,谁能拒绝一个 screenfetch 呢?

配置 Docker 容器代理#
注意,这不是代理 Docker 的软件源,而是代理 Docker 容器内的网络。
编辑 ~/.docker/config.json 文件,添加以下内容:
{
"proxies": {
"default": {
"httpProxy": "http://proxy.example.com:8080",
"httpsProxy": "http://proxy.example.com:8080"
}
}
}
这里的 httpProxy 和 httpsProxy 需要根据你实际的代理设置进行修改。