尽管Docker/Podman容器的使用方式与虚拟机不同,但对于“开发环境”,我们还是倾向于将其当作虚拟机来使用,就如同物理机器一样。但全虚拟化的虚拟机(如kvm)还是会对性能有影响,尤其是对于I/O密集型应用,LXC/LXD应当是不错的选择,但实际上在“装机必备”的Docker上,也是能实现这样的功能。
下方的Dockerfile就描述了一个这样的“完整”Ubuntu容器,其像标准Ubuntu一样由systemd作为init,并运行SSH服务器,以更方便的远程访问,或远程使用vscode remote。其还创建了一个普通用户,用户名、UID和GID可以与你宿主机上保持一致,以更方便的共享文件。
Github Gist: https://gist.github.com/WuSiYu/bbee5788242bcb99b9acbe5257aae522
FROM ubuntu:latest
LABEL maintainer="SiYu Wu <wu.siyu@hotmail.com>"
ENV DEV_USER=user
ENV UID=1000
ENV GID=1000
ENV DEF_PASSWD=password
ENV TZ=Asia/Shanghai
ENV LANG=en_US.UTF-8
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone && \
yes | unminimize && \
apt install -y systemd sudo openssh-server bash-completion zsh git curl vim && \
addgroup --gid $GID $DEV_USER && \
adduser --uid $UID --gid $GID --gecos "" --disabled-password $DEV_USER && \
usermod -aG sudo $DEV_USER && \
echo "$DEV_USER:$DEF_PASSWD" | chpasswd && \
systemctl mask systemd-resolved.service && \
echo "LANG=$LANG" > /etc/default/locale && \
cp /usr/share/doc/util-linux/examples/securetty /etc/securetty
CMD ["systemd"]
在标准Ubuntu Docker镜像基础上,执行了以下操作:
- 设置时区
- 去“精简化”
- 安装systemd、sudo、SSH服务器、bash自动补全和一些其他工具
- 新建用户并赋予sudo权限
- 禁用systemd-resolved.service,因为Docker已经为我们配置好了容器的DNS
- 设置语言
- 补全/etc/securetty
使用示例
为保证镜像的安全性(更新及时),未维护Docker Hub上维护镜像,请自行构建
构建镜像
sudo docker build -t devbox:v0.1 .
启动镜像(非特权模式)
需要赋予容器audit(审计信息)写入权限,否则容器的ssh、sudo等软件会工作不正常
sudo docker run -d -it --cap-add AUDIT_WRITE --name devbox --publish 8022:22 --hostname devbox -v ./data:/data:z devbox
启动镜像(特权模式)
sudo podman run -it --name devbox --publish 8022:22 --hostname devbox -v ./data:/data --privileged devbox
限制与可选操作
首先此方法的“隔离型”不如lxc/lxd方式,哪怕是非特权模式,容器的audit信息也会被写入到host(若禁止则会导致容器工作不正常),大概是因为Docker本身就没有对此进行隔离。
其次你会发现apt的软件包名的shell自动补全无法正常工作,这是因为ubuntu的官方docker镜像中禁用了apt的一些缓存功能,以避免在构建镜像时产生一些无用的缓存。考虑到容器性质的用途,此处保留了这个特性。如果你希望能正常使用软件包名自动补全功能,删除/etc/apt/apt.conf.d/docker-clean
文件即可。