DOCKER(参考)
操作镜像
拉取镜像
$ docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]
# 比如
$ docker pull ubuntu:18.04
18.04: Pulling from library/ubuntu
92dc2a97ff99: Pull complete
be13a9d27eb8: Pull complete
c8299583700a: Pull complete
Digest: sha256:4bc3ae6596938cb0d9e5ac51a1152ec9dcac2a1c50829c74abd9c4361e321b26
Status: Downloaded newer image for ubuntu:18.04
docker.io/library/ubuntu:18.04
列出镜像
$ docker image ls
$ docker images
$ docker
# 查看镜像、容器、数据卷所占用的空间。
$ docker system df
中间层镜像
- 为了加速镜像构建、重复利用资源,Docker 会利用 中间层镜像。
- 所以在使用一段时间后,可能会看到一些依赖的中间层镜像。
- 默认的
docker image ls 列表中只会显示顶层镜像,如果希望显示包括中间层镜像在内的所有镜像的话,需要加 -a 参数。
docker image ls -a
列出部分镜像
# 根据仓库名列出镜像
$ docker image ls ubuntu
# 列出特定的某个镜像
$ docker image ls ubuntu:18.04
# docker image ls 还支持强大的过滤器参数 --filter,或者简写 -f
$ docker image ls -f since=mongo:3.2
REPOSITORY TAG IMAGE ID CREATED SIZE
redis latest 5f515359c7f8 5 days ago 183 MB
nginx latest 05a60462f8ba 5 days ago 181 MB
删除本地镜像
$ docker image rm [选项] <镜像1> [<镜像2> ...]
镜像可以是:
- 镜像名:tag
- 镜像id
- 镜像摘要
docker image ls --digests # 查看摘要
# 用 docker image ls 命令来配合
# 删除所有仓库名为 redis 的镜像
$ docker image rm $(docker image ls -q redis)
# 删除所有在 mongo:3.2 之前的镜像
$ docker image rm $(docker image ls -q -f before=mongo:3.2)
操作容器
新建并启动
# 输出一个 “Hello World”,之后终止容器
docker run ubuntu:18.04 /bin/echo "Hello World"
# 启动一个 bash 终端,允许用户进行交互
docker run -i -t ubuntu:18.04 /bin/bash
# -t 选项让Docker分配一个伪终端(pseudo-tty),并绑定到容器的标准输入上
# -i 则让容器的标准输入保持打开
# 只用 -i 参数时,由于没有分配伪终端,界面没有我们熟悉的 Linux 命令提示符,但命令执行结果仍然可以返回。
利用 docker run 来创建容器时,Docker 在后台运行的标准流程如下:
- 检查本地是否存在指定的镜像,不存在就从 registry 下载
- 利用镜像创建并启动一个容器
- 分配一个文件系统,并在只读的镜像层外面挂载一层可读写层
- 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去
- 从地址池配置一个 ip 地址给容器
- 执行用户指定的应用程序
- 执行完毕后容器被终止
启动已终止容器
# 查看正在运行的容器
docker ps
# 查看所有容器(包括已终止的容器)
docker ps -a
# 重新启动已终止的容器
docker container start 容器id
容器的核心为所执行的应用程序,所需要的资源都是应用程序运行所必需的。除此之外,并没有其它的资源。
守护态运行
# 不使用 -d 参数运行容器,容器会把输出的结果 (STDOUT) 打印到宿主机上面
$ docker run ubuntu:18.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"
# 使用了 -d 参数运行容器
$ docker run -d ubuntu:18.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"
# 查看输出
$ docker logs 容器id
$ docker container logs 容器id
终止容器
$ docker container stop 容器id
# 当 Docker 容器中指定的应用终结时,容器也自动终止
# 容器内退出 exit ctrl+d
# 终止状态的容器可以用
docker container ls -a
删除容器
# 删除一个处于终止状态的容器
$ docker container rm 容器id
# 要删除一个运行中的容器
$ docker container rm -f 容器id
# 清理所有处于终止状态的容器
$ docker container prune
进入容器
# 在使用 -d 参数时,容器启动后会进入后台, 某些时候需要进入容器进行操作
# 方法一:attach
docker attach 容器id
# 从这个 stdin 中 exit,会导致容器的停止(所以方法一,不推荐)
# 方法二:exec
docker exec -it 容器id
# 从这个 stdin 中 exit,不会导致容器的停止(推荐)
容器的导出和导入
# 导出容器快照到本地文件
docker export 容器id > ubuntu.tar
# 导入容器快照文件中为镜像
docker import ubuntu.tar test/ubuntu:v1.0
# 也可以通过指定 URL 或者某个目录来导入
$ docker import http://example.com/exampleimage.tgz example/imagerepo
定制镜像(参考)
docker commit
docker run --name webserver -d -p 8080:80 nginx
docker exec -it webserver bash
echo 'Hello, Docker!' > /usr/share/nginx/html/index.html
exit
# 我们修改了容器的文件,也就是改动了容器的存储层
# docker diff 命令能看到具体的改动
$ docker diff webserver
# 现在我们定制好了变化,我们希望能将其保存下来形成镜像
# docker commit 的语法格式为:
$ docker commit [选项] <容器ID或容器名> [<仓库名>[:<标签>]]
# 用下面的命令将容器保存为镜像:
$ docker commit --author "realguo" --message "修改了网页" webserver nginx:v2
# 查看镜像内的历史记录
$ docker history nginx:v2
# 运行定制的镜像
$ docker run --name webserver2 -d -p 8081:80 nginx:v2
- 当我们运行一个容器的时候(如果不使用卷的话),我们做的任何文件修改都会被记录于容器存储层里
- 而 Docker 提供了一个 ·
docker commit 命令,可以将容器的存储层保存下来成为镜像 - 换句话说,就是在原有镜像的基础上,再叠加上容器的存储层,并构成新的镜像
- 以后我们运行这个新镜像的时候,就会拥有原有容器最后的文件变化。
慎用docker commit
- 使用
docker commit 命令虽然可以比较直观的帮助理解镜像分层存储的概念,但是实际环境中并不会这样使用。 - 首先,如果仔细观察之前的
docker diff webserver 的结果,你会发现除了真正想要修改的 /usr/share/nginx/html/index.html 文件外,由于命令的执行,还有很多文件被改动或添加了。 - 这还仅仅是最简单的操作,如果是安装软件包、编译构建,那会有大量的无关内容被添加进来,将会导致镜像极为臃肿。
- 此外,使用
docker commit 意味着所有对镜像的操作都是黑箱操作,生成的镜像也被称为 黑箱镜像, - 换句话说,就是除了制作镜像的人知道执行过什么命令、怎么生成的镜像,别人根本无从得知。
- 而且,即使是这个制作镜像的人,过一段时间后也无法记清具体的操作。这种黑箱镜像的维护工作是非常痛苦的。
- 而且,回顾之前提及的镜像所使用的分层存储的概念,除当前层外,之前的每一层都是不会发生改变的,
- 换句话说,任何修改的结果仅仅是在当前层进行标记、添加、修改,而不会改动上一层。
- 如果使用
docker commit 制作镜像,以及后期修改的话,每一次修改都会让镜像更加臃肿一次, - 所删除的上一层的东西并不会丢失,会一直如影随形的跟着这个镜像,即使根本无法访问到。这会让镜像更加臃肿。
使用 Dockerfile 定制镜像
- 从刚才的
docker commit 的学习中,我们可以了解到,镜像的定制实际上就是定制每一层所添加的配置、文件 - 如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么之前提及的无法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。
- 这个脚本就是 Dockerfile。
# 1.创建空白目录
mkdir mynginx
# 2.创建Dockerfile
touch Dockerfile
# 3.向Dockerfile中写入以下内容
FROM nginx
RUN echo '<h1>Hello, Docker</h1>' > /usr/share/nginx/html/index.html
# 这个 Dockerfile 很简单,一共就两行。涉及到了两条指令,FROM 和 RUN
# 4. 构建镜像
$ docker build -t nginx:v3 .
- 我们要理解
docker build 的工作原理。Docker 在运行时分为 Docker 引擎(也就是服务端守护进程)和客户端工具。Docker 的引擎提供了一组 REST API,被称为 Docker Remote API,而如 docker 命令这样的客户端工具,则是通过这组 API 与 Docker 引擎交互,从而完成各种功能。因此,虽然表面上我们好像是在本机执行各种 docker 功能,但实际上,一切都是使用的远程调用形式在服务端(Docker 引擎)完成。也因为这种 C/S 设计,让我们操作远程服务器的 Docker 引擎变得轻而易举。
数据管理(参考)
数据卷
数据卷 是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性:
数据卷 可以在容器之间共享和重用- 对
数据卷 的修改会立马生效 - 对
数据卷 的更新,不会影响镜像 数据卷 默认会一直存在,即使容器被删除
# 创建一个数据卷
docker volume create my-vol
# 查看数据卷
docker volume ls
# 查看指定数据卷的信息
docker volume inspect my-vol
# 启动一个挂载数据卷的容器
docker run -d -P \
--name web \
--mount source=my-vol,target=/usr/share/nginx/html \
nginx:alpine
# 查看数据卷的具体信息
docker inspect web
# 删除数据卷
docker volume rm my-vol
# 删除容器,不会删除数据卷,加上-v则可以
docker container rm -v 容器名
# 删除无主的数据卷
docker volume prune
挂在主机目录
# 挂在一个主机目录作为数据卷
docker run -d -P --name webserver --mount type=bind,source=/root/dockertest/webapp,target=/usr/share/nginx/html,readonly nginx
# 注意点:
这种方式,容器原先目录中的内容就会没有了
|