本文介绍如何在 docker Ubuntu 容器中安装 docker,从而可以在容器中再创建容器,实现套娃!
root@ubuntu20:~# docker run -itd --name ubuntu --privileged --cap-add=NET_ADMIN ubuntu:20.04
350983744ebfbc2d7828ef24256b7b5a7d4ce4dd97e083e173c10f2dca4fa097
root@ubuntu20:~# docker exec -it ubuntu bash
root@350983744ebf:/#
root@350983744ebf:/# sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list
root@350983744ebf:/# sed -i s@/security.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list
root@350983744ebf:/# apt-get update
Get:1 http://mirrors.aliyun.com/ubuntu focal InRelease [265 kB]
Get:2 http://mirrors.aliyun.com/ubuntu focal-updates InRelease [114 kB]
Get:3 http://mirrors.aliyun.com/ubuntu focal-backports InRelease [108 kB]
Get:4 http://mirrors.aliyun.com/ubuntu focal-security InRelease [114 kB]
Get:5 http://mirrors.aliyun.com/ubuntu focal/multiverse amd64 Packages [177 kB]
Get:6 http://mirrors.aliyun.com/ubuntu focal/restricted amd64 Packages [33.4 kB]
Get:7 http://mirrors.aliyun.com/ubuntu focal/universe amd64 Packages [11.3 MB]
Get:8 http://mirrors.aliyun.com/ubuntu focal/main amd64 Packages [1275 kB]
Get:9 http://mirrors.aliyun.com/ubuntu focal-updates/universe amd64 Packages [1421 kB]
Get:10 http://mirrors.aliyun.com/ubuntu focal-updates/restricted amd64 Packages [3092 kB]
Get:11 http://mirrors.aliyun.com/ubuntu focal-updates/multiverse amd64 Packages [32.0 kB]
Get:12 http://mirrors.aliyun.com/ubuntu focal-updates/main amd64 Packages [3633 kB]
Get:13 http://mirrors.aliyun.com/ubuntu focal-backports/main amd64 Packages [55.2 kB]
Get:14 http://mirrors.aliyun.com/ubuntu focal-backports/universe amd64 Packages [28.6 kB]
Get:15 http://mirrors.aliyun.com/ubuntu focal-security/universe amd64 Packages [1117 kB]
Get:16 http://mirrors.aliyun.com/ubuntu focal-security/restricted amd64 Packages [2942 kB]
Get:17 http://mirrors.aliyun.com/ubuntu focal-security/main amd64 Packages [3145 kB]
Get:18 http://mirrors.aliyun.com/ubuntu focal-security/multiverse amd64 Packages [29.3 kB]
Fetched 28.9 MB in 3s (8636 kB/s)
Reading package lists... Done
apt-get install docker.io
需要安装400多M的一大堆程序。
因为 docker 容器中,systemctl 程序已经不管用了,所以安装完 docker 后,系统并不会自动启动 docker 服务。需要手动添加服务启动脚本:
apt-get install vim
vi /etc/init.d/docker
新建 /etc/init.d/docker 文件,内容如下:
#!/bin/sh
set -e
### BEGIN INIT INFO
# Provides: docker
# Required-Start: $syslog $remote_fs
# Required-Stop: $syslog $remote_fs
# Should-Start: cgroupfs-mount cgroup-lite
# Should-Stop: cgroupfs-mount cgroup-lite
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Create lightweight, portable, self-sufficient containers.
# Description:
# Docker is an open-source project to easily create lightweight, portable,
# self-sufficient containers from any application. The same container that a
# developer builds and tests on a laptop can run at scale, in production, on
# VMs, bare metal, OpenStack clusters, public clouds and more.
### END INIT INFO
export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
BASE=docker
# modify these in /etc/default/$BASE (/etc/default/docker)
DOCKERD=/usr/bin/dockerd
# This is the pid file managed by docker itself
DOCKER_PIDFILE=/var/run/$BASE.pid
# This is the pid file created/managed by start-stop-daemon
DOCKER_SSD_PIDFILE=/var/run/$BASE-ssd.pid
DOCKER_LOGFILE=/var/log/$BASE.log
DOCKER_OPTS=
DOCKER_DESC="Docker"
# Get lsb functions
. /lib/lsb/init-functions
if [ -f /etc/default/$BASE ]; then
. /etc/default/$BASE
fi
# Check docker is present
if [ ! -x $DOCKERD ]; then
log_failure_msg "$DOCKERD not present or not executable"
exit 1
fi
fail_unless_root() {
if [ "$(id -u)" != '0' ]; then
log_failure_msg "$DOCKER_DESC must be run as root"
exit 1
fi
}
case "$1" in
start)
fail_unless_root
touch "$DOCKER_LOGFILE"
chgrp docker "$DOCKER_LOGFILE"
ulimit -n 1048576
# Having non-zero limits causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
if [ "$BASH" ]; then
ulimit -u unlimited
else
ulimit -p unlimited
fi
log_begin_msg "Starting $DOCKER_DESC: $BASE"
start-stop-daemon --start --background \
--no-close \
--exec "$DOCKERD" \
--pidfile "$DOCKER_SSD_PIDFILE" \
--make-pidfile \
-- \
-p "$DOCKER_PIDFILE" \
$DOCKER_OPTS \
>> "$DOCKER_LOGFILE" 2>&1
log_end_msg $?
;;
stop)
fail_unless_root
if [ -f "$DOCKER_SSD_PIDFILE" ]; then
log_begin_msg "Stopping $DOCKER_DESC: $BASE"
start-stop-daemon --stop --pidfile "$DOCKER_SSD_PIDFILE" --retry 10
log_end_msg $?
else
log_warning_msg "Docker already stopped - file $DOCKER_SSD_PIDFILE not found."
fi
;;
restart)
fail_unless_root
docker_pid=$(cat "$DOCKER_SSD_PIDFILE" 2> /dev/null || true)
[ -n "$docker_pid" ] \
&& ps -p $docker_pid > /dev/null 2>&1 \
&& $0 stop
$0 start
;;
force-reload)
fail_unless_root
$0 restart
;;
status)
status_of_proc -p "$DOCKER_SSD_PIDFILE" "$DOCKERD" "$DOCKER_DESC"
;;
*)
echo "Usage: service docker {start|stop|restart|status}"
exit 1
;;
esac
然后加上可执行权限:
chmod +x /etc/init.d/docker
接着就可以启动 docker 服务:
root@350983744ebf:/# service docker start
* Starting Docker: docker [ OK ]
root@350983744ebf:/# service docker status
* Docker is running
root@350983744ebf:/# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
我们再在容器中启动一个 Ubuntu 容器:
root@350983744ebf:/# docker run -itd --name ubuntu --privileged --cap-add=NET_ADMIN ubuntu:20.04
Unable to find image 'ubuntu:20.04' locally
20.04: Pulling from library/ubuntu
96d54c3075c9: Pull complete
Digest: sha256:ed4a42283d9943135ed87d4ee34e542f7f5ad9ecf2f244870e23122f703f91c2
Status: Downloaded newer image for ubuntu:20.04
53ec4adbb55196fad5b31cdbf81ec9fe1e8229bb2df7be47b220911cc8bd0a7d
root@350983744ebf:/# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
53ec4adbb551 ubuntu:20.04 "/bin/bash" 8 seconds ago Up 6 seconds ubuntu
这就实现了容器的套娃!