docker 的部署与快速使用,首先,容器是每个用户个人使用的,镜像是提前部署好的,用户根据镜像,建立自己的容器进行开发使用。容器内部是独立的
本文档介绍了如何在宿主机系统上进行 Docker 服务的部署,以及如何创建 Docker 镜像、
如何创建并运行 Docker 容器等,本文档的测试环境所用的宿主机系统是 Ubuntu16.04,具体信息如下。
$ uname -a
Linux ubuntu 4.10.0-28-generic #32~16.04.2-Ubuntu SMP Thu Jul 20 10:19:48 UTC 2017
x86_64 x86_64 x86_64 GNU/Linux
部署完成的 Docker 版本是 19.03.11。
$ docker --versi
Docker version 19.03.11, build 42e35e61f3
使用的话,可以直接看最后一章
① 如果从 Ubuntu 官方的源下载速度慢,可尝试把源更换为清华源
# 先备份原来的 source.list 文件。
$ sudo cp /etc/apt/source.list /etc/apt/source.list.b
# 打开 source.list 文件添加以下内容
$ sudo vi /etc/apt/source.li
清华源替换手册
② 安装 https 相关的软
$ sudo apt-get update
$ sudo apt-get install apt-transport-https
$ sudo apt-get install ca-certificates
$ sudo apt-get install curl
$ sudo apt-get install software-properties-common
③ 设置 Docker 的 apt 仓库地址
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -3
$ sudo add-apt-repository "deb [arch=amd64] \ https://download.docker.com/linux/ubuntu \
$ (lsb_release -cs) \ stable"
# 如果长时间无响应,可尝试把源更换为清华源
④ 安装 Docker 软件包
$ sudo apt-get install docker-ce
⑤ 测试 Docker 服务是否已部署成功
$ sudo docker run hello-world
$ docker --version
Docker version 19.03.9, build 9d988398e7
此步主要解决运行 Docker 命令时需要 sudo 权限的问题
# 创建新的用户组 docker
$ sudo groupadd docker
# 添加用户组 docker 到用户 clare 的附加群组
$ sudo usermod -aG docker clare
# 查看 docker 用户组是否已添加到用户 clare 的附加群组
$ cat /etc/group |grep docker
docker:x:999:clare
# 退出用户,重新登录使以上配置生效
$ logout
默认情况下 Docker 服务会自启。手动停止和开启 Docker 服务可参考以下命令
# 开启 Docker 服务
$ sudo service docker start
# 停止 Docker 服务。注意:Docker 服务一旦停止,所有的容器也会停止
$ sudo service docker stop
# 重启 Docker 服务。
$ sudo service docker restart
# 运行以下命令会从 Docker 仓库拉取 Ubuntu16.04 镜像到本地
$ docker pull ubuntu:16.04
16.04: Pulling from library/ubuntu
e92ed755c008: Pull complete
b9fd7cb1ff8f: Pull complete
ee690f2d57a1: Pull complete
53e3366ec435: Pull complete
Digest:
sha256:db6697a61d5679b7ca69dbde3dad6be0d17064d5b6b0e9f7be8d456ebb337209
Status: Downloaded newer image for ubuntu:16.04
docker.io/library/ubuntu:16.04
注:Usage: docker pull
Docker 中镜像名是由仓库名 REPOSITORY 和标签名 TAG 组成。
$ docker images
$ docker rmi hello-world:latest
注:Usage: docker rmi IMAGE
docker rmi 后指定要删除的镜像,可以是镜像名 REPOSITORY:TAG,也可以是镜像
的 IMAGE ID。
① 编写 Dockerfile
$ touch Dockerfile
$ vi Dockerfile
# 添加以下内容到 Dockerfile 中,基于 Ubuntu16.04 镜像创建新的镜像,并安装
# 常用的 vim、ifconfig 等命令依赖的软件包。
FROM ubuntu:16.04
RUN apt-get update \
&& apt-get -y install sudo vim net-tools iputils-ping openssh-server \
git curl unzip samba nfs-kernel-server nfs-common minicom
CMD /bin/bash
注:以上仅仅是一个简单的 Dockerfile 模板,可根据具体需求继续添加命令(如添加
所需软件包到 apt-get -y install 之后)。
② 根据 Dockerfile 创建镜像
# 使用当前目录下的 Dockerfile 创建新镜像:ubuntu_clare:16.04_20200604
$ docker build -t ubuntu_clare:16.04_20200604 ./
$ docker images
注:Usage: docker build -t
1. docker build 命令中 -t
2. docker build 命令中 DOCKERFILE_PATH 是指定的 Dockerfile 所在目录。
# 将名称为 ubuntu_atu:16.04_20200604 的 Docker 镜像打包在 image.tar 中。
$ docker save -o image.tar ubuntu_atu:16.04_20200604
$ ls -lh image.tar
注:Usage: docker save -o ARCHIVE_NAME
1. docker save 命令中 -o ARCHIVE_NAME 的作用是指定打包保存到哪个文件。
2. docker save 命令中 -o
# 加载当前目录下的 Docker 镜像包 image.tar。
$ docker load -i image.tar
注:Usage: docker load -i ARCHIVE_NAME
1. docker load 命令中 -i ARCHIVE_NAME 的作用是指定加载的镜像包文件名。
2. 注意:运行命令加载镜像包中的镜像后,会覆盖本地镜像库中已有的同名镜像。
运行 docker run 命令会创建并运行一个新的 Docker 容器。
# 基于镜像 ubuntu_atu:16.04_20200604 创建名称为 ubuntu16.04_felix 的容器,
# 设置容器中的 Ubuntu 系统 hostname 为 ubuntu16,并挂载指定的宿主机目录
# /home/felix 到容器中的 /home 目录下。
$ docker run -it --name ubuntu16.04_felix --hostname ubuntu16 \
-v /home/felix:/home ubuntu_atu:16.04_20200604 /bin/bash
注:Usage: docker run -it --name CONTAINER --hostname HOSTNAME \
-v HOST_PATH:CONTAINER_PATH \
1. docker run 命令中 -it 的作用是以交互模式(--interactive)运行容器并分配一个伪
串口(--tty)。
2. docker run 命令中 --hostname HOSTNAME 的作用是指定容器中 Ubuntu 系统的
hostname(会显示在终端的 root@ 之后)。
3. docker run 命令中 -v HOST_PATH:CONTAINER_PATH 的作用是通过 bind mount
方式挂载宿主机目录到容器中。挂载到容器中的位置 CONTAINER_PATH 建议是在
容器中的 /home 目录下(可以是新建的子目录)。
4. docker run 命令中最后的 COMMAND 是创建容器后自动运行的命令,一般是启动
bash 的命令 /bin/bash。目的是让容器创建后至少有一个正在运行的进程,否则容
器状态会变成 Exited。
Docker 容器的状态一般有两种:Up(容器正在运行)和 Exited(容器已经退出)。
# 显示所有容器的信息。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED
STATUS PORTS NAMES
69ad94a86022 ubuntu_atu:16.04_20200604 "/bin/bash" About an hour ago
Up 1 second ubuntu16.04_felix
# 只显示容器 ID、镜像名、容器状态和容器名。
$ docker ps -a --format "table{{.ID}}\t{{.Image}}\t{{.Status}}\t{{.Names}}"
在刚创建容器后运行的终端里直接按 Ctrl + D 或运行 exit 命令会直接停止容器,容器中的
系统会停止运行。不停止容器的前提下切换终端回到宿主机的方法是:先按下 Ctrl + P,然
后按下 Ctrl + Q。
root@ubuntu16:/#
# 先按下 Ctrl + P,然后按下 Ctrl + Q。
root@ubuntu16:/# read escape sequence
# 接下来就会回到宿主机的终端
felix@atu:~$
$ docker exec -it ubuntu16.04_felix /bin/bash
root@ubuntu16:/#
注:Usage: docker exec -it CONTAINER /bin/bash
1. CONTAINER 可以是容器 ID 或者容器名。
2. 还有另一条命令 docker attach 也可以切换终端回到 Docker 容器,区别在于通过
docker attach 进入的容器,终端按下 Ctrl + D 或运行 exit 命令后,容器也会停
止。而通过 docker exec 进入的则不会
$ docker stop ubuntu16.04_felix
$ docker start ubuntu16.04_felix
注:Usage: docker stop CONTAINER
docker start CONTAINER
CONTAINER 可以是容器 ID 或者容器名。
$ docker rm ubuntu16.04_felix
注:Usage: docker rm CONTAINER
删除前先确认容器已停止(状态是 Exited)。容器删除后无法恢复,请谨慎执行
$ docker rename ubuntu16.04_felix ubuntu16.04_rename
$ docker ps -a
注:Usage: docker rename CONTAINER NEW_NAME
如果在创建容器时已指定了挂载目录,则只需把文件放到挂载的宿主机目录下,容器中即可
直接访问。如果没有挂载,可以使用 docker cp 命令进行传输。
# 复制宿主机中的文件 filetest 到容器 ubuntu16.04_felix 的 /home 目录下。
$ docker cp filetest ubuntu16.04_felix:/home
# 复制容器中的目录 /home/dirtest/ 到宿主机的当前目录。
$ docker cp ubuntu16.04_felix:/home/dirtest/ ./
注:Usage: docker cp SRC_PATH CONTAINER:DEST_PATH
docker cp CONTAINER:SRC_PATH DEST_PATH
在宿主机上使用 docker cp 命令既可以复制宿主机中的文件(或目录)到容器,也可
以复制容器中的文件(或目录)到宿主机。
# 将名称为 ubuntu16.04_felix 的容器保存为镜像 ubuntu:16.04_v2_20200604。
$ docker commit ubuntu16.04_felix ubuntu_atu:16.04_v2_20200604
$ docker images
注:Usage: docker commit CONTAINER
1. docker commit 命令中 CONTAINER 是需要保存的容器名。
2. docker commit 命令中
通用脚本
#!/bin/bash
# This script would help you run a docker container quickly.
# example for input
# CONTAINER_NAME="ubuntu14.04"
# IMAGE_REPO="ubuntu"
# IMAGE_TAG="14.04"
# HOST_PATH="/home/xx/workspace"
# CONTAINER_PATH="/home/workspace"
# HOST_NAME="ubuntu14"
echo
echo "This script would help you run a docker container quickly."
echo
echo "You can refer to the following existing container:"
echo "(NOTICE: a new container name is required to be different)"
echo
docker ps -a --format "table {{.ID}}\t{{.Names}}\t{{.Image}}\t{{.Status}}\t{{.CreatedAt}}"
echo
read -e -p "1. input a NEW container name : " CONTAINER_NAME
echo
echo
echo "You can run a container based on one of the following image:"
docker images
echo
read -e -p "2. input based image REPOSITORY : " IMAGE_REPO
read -e -p "3. input based image TAG : " IMAGE_TAG
echo
read -e -p "4. input mount host path : " HOST_PATH
read -e -p "5. input mount container path : " CONTAINER_PATH
echo
read -e -p "6. input container's host name : " HOST_NAME
echo
echo
echo "Please check the follow information for your new container:"
echo "1. container name : $CONTAINER_NAME"
echo "2. image repository : $IMAGE_REPO"
echo "3. image tag : $IMAGE_TAG"
echo "4. host path : $HOST_PATH"
echo "5. container path : $CONTAINER_PATH"
echo "6. host name : $HOST_NAME"
echo
echo
read -e -p "Want to run a docker container? [Y/n] " input
case $input in
[nN])
echo
echo "abort running docker container."
echo
exit 1
;;
*)
echo
echo "start running your docker container, please wait..."
echo
echo
;;
esac
# Create an user account in container.
# The user name and uid are the same as the account on host.
USER_NAME=$USER
USER_ID=$(id -u $USER)
echo "create user name of $USER_NAME and uid of $USER_ID."
echo
echo -n "new container id: "
# Run backaround using "-d".
docker run -tid --name ${CONTAINER_NAME} \
--hostname ${HOST_NAME} \
-v ${HOST_PATH}:${CONTAINER_PATH} \
${IMAGE_REPO}:${IMAGE_TAG} \
/bin/bash
echo
echo
echo "now enter to the shell of container..."
echo "(TIPS: press Ctrl + P and then Ctrl + Q to leave the shell of container)"
echo
echo
echo "NOTICE:"
echo
echo "1. please set password for $USER first, using [passwd $USER]."
echo
echo "2. after setting password, please switch the accout to $USER using [su $USER]."
echo
echo
# Create a user account using the CURRENT user name and uid.
docker exec ${CONTAINER_NAME} useradd -u $USER_ID -m $USER_NAME --shell /bin/bash
# Add to the sudo group.
docker exec ${CONTAINER_NAME} usermod -G sudo $USER_NAME
# Enter the container.
docker exec -it ${CONTAINER_NAME} /bin/bash
本章面向 Docker 服务的使用者,主要介绍了如何通过 docker_run.sh 脚本在宿主机上快速创
建并运行一个自定义配置的 Docker 容器。
以下示例运行 docker_run.sh 脚本,主要完成以下功能:
① 创建并运行一个名称为 ubuntu16.04_felix 的容器。
② 该容器基于 ubuntu_atu:16.04_20200604 镜像。
③ 运行后会在容器的 Ubuntu 系统中新建一个与当前用户相同用户名和 uid 的用户。
④ 将指定的宿主机目录 /home/felix/workspace/hisilicon/Hi3562V100/ 挂载到容器中指定
的目录 /home/workspace 下。
⑤ 设置容器的 Ubuntu 系统的 hostname 为 ubuntu16。
$ ./docker_run.sh
This script would help you run a docker container quickly.
You can refer to the following existing container:
(NOTICE: a new container name is required to be different)
CONTAINER ID NAMES IMAGE STATUS
CREATED AT
ef6d83e41c13 ubuntu14.04_felix ubuntu_atu:14.04_20200604 Up 14 minutes
2020-06-04 01:57:54 -0400 EDT
# 输入新的容器名(请与已有的容器命名方式保持一致)。
1. input a NEW container name : ubuntu16.04_felix
# 输入容器基于的镜像所在仓库名(从上表中查阅)
2. input based image REPOSITORY : ubuntu_atu
# 输入容器基于的镜像的标签名(从上表中查阅)。
3. input based image TAG : 16.04
# 输入要挂载到容器中的宿主机目录。(因为容器独立,所以想使用外部的文件的话,需要将外部的文件夹挂载到容器中)
4. input mount host path : /home/felix/workspace/
# 输入要挂载到容器中的目录(建议挂载到 /home 目录下,且不要和用户名重名)
5. input mount container path : /home/workspace
# 输入容器中系统的 hostname(建议和 Ubuntu 版本号一致,以便使用时区分开)
6. input container's host name : ubuntu16
# 检查输入信息是否有误。如果有误,可按 Ctrl + C 退出脚本,重新运行。
Please check the follow information for your new container:
1. container name : ubuntu16.04_felix
2. image repository : ubuntu_atu
3. image tag : 16.04_20200604
4. host path : /home/felix/workspace/hisilicon/Hi3562V100/
5. container path : /home/workspace
14
6. host name : ubuntu16
Want to run a docker container? [Y/n]
# 确认无误后,按下 Enter 键开始创建并运行 Docker 容器
start running your docker container, please wait...
# 脚本会自动在容器中的系统创建一个新用户,拥有与当前用户相同的用户名和 uid。
create user name of felix and uid of 1001.
new container id: 90d8082320cca05b8bb8e7570cfae3a0da40ebcf468954a048a2af42aaf9cdef
now enter to the shell of container...
(TIPS: press Ctrl + P and then Ctrl + Q to leave the shell of container)
NOTICE:
1. please set password for felix first, using [passwd felix].
2. after setting password, please switch the accout to felix using [su felix].
root@ubuntu16:/#
# 以下已进入到容器中的 Ubuntu 系统的终端。
root@ubuntu16:/#
# 为容器中的新用户设置密码
root@ubuntu16:/# passwd felix
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
# 切换到新用户(一般情况下不要使用 root 用户做开发)。
root@ubuntu16:/# su felix
# 验证是否可以访问宿主机挂载在容器上的目录
felix@ubuntu16:/$ cd /home/workspace/
felix@ubuntu16:/home/workspace$ ls
注:1. docker images 显示的 Docker 镜像中,仓库名(REPOSITORY)为 ubuntu 的是
从 Docker 仓库拉取下来的原始镜像,仓库名为 ubuntu_atu 的是基于原始镜像安装
了一些常用命令所依赖的软件包之后的镜像。
2. 在进入到容器后,请先根据脚本的提示设置新用户的密码,并切换到新用户下。由
于 Docker 容器中的用户 ID 是和宿主机共用的,所以建议不要在 Docker 容器中
再创建新的用户。
3. 使用容器时请不要登录 root 用户进行操作,特别是不要在 root 用户下对挂载到容
器中的宿主机目录进行操作。如果遇到必须使用 root 用户才能执行的操作(比如
cd 进入根目录下的某些目录),可使用命令 sudo su 暂时切换到 root 用户。
# 按下 Ctrl + P,再按下 Ctrl + Q 可以切换终端回到宿主机
felix@ubuntu16:/host$ read escape sequence
felix@atu:~$
# 回到正在运行的容器(以新建的普通用户 felix 进入)
felix@atu:~$ docker exec -it -u felix ubuntu16.04_felix /bin/bash
felix@ubuntu16:/#
6. 参考资料
叶正轩的 docker 搭建笔记