Reference:
Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。
Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。
Docker 是一个用于开发,交付和运行应用程序的开放平台。Docker 使您能够将应用程序与基础架构分开,从而可以快速交付软件。借助 Docker,您可以与管理应用程序相同的方式来管理基础架构。通过利用 Docker 的方法来快速交付,测试和部署代码,您可以大大减少编写代码和在生产环境中运行代码之间的延迟。
快速,一致地交付您的应用程序
Docker 允许开发人员使用您提供的应用程序或服务的本地容器在标准化环境中工作,从而简化了开发的生命周期。
容器非常适合持续集成和持续交付(CI / CD)工作流程,请考虑以下示例方案:
响应式部署和扩展
Docker 是基于容器的平台,允许高度可移植的工作负载。Docker 容器可以在开发人员的本机上,数据中心的物理或虚拟机上,云服务上或混合环境中运行。
Docker 的可移植性和轻量级的特性,还可以使您轻松地完成动态管理的工作负担,并根据业务需求指示,实时扩展或拆除应用程序和服务。
在同一硬件上运行更多工作负载
Docker 轻巧快速。它为基于虚拟机管理程序的虚拟机提供了可行、经济、高效的替代方案,因此您可以利用更多的计算能力来实现业务目标。Docker 非常适合于高密度环境以及中小型部署,而您可以用更少的资源做更多的事情。
鉴于教程中的,使用官方安装脚本自动安装有问题,可以使用链接中的手动安装。
为了能在非sudo
模式下使用Docker
, 需要将当前用户加入Docker Group
。
sudo usermod -aG docker $USER
为了使上述变更生效,请先Logout,再Login
Docker 允许你在容器内运行应用程序, 使用 docker run
命令来在容器内运行一个应用程序。
docker: Docker 的二进制执行文件。
run: 与前面的 docker 组合来运行一个容器。
ubuntu:15.10 指定要运行的镜像,Docker 首先从本地主机上查找镜像是否存在,如果不存在,Docker 就会从镜像仓库 Docker Hub 下载公共镜像。(从图中可以看见,真的下载了)
/bin/echo “Hello world”: 在启动的容器里执行的命令
以上命令完整的意思可以解释为:Docker 以 ubuntu15.10 镜像创建一个新容器,然后在容器里执行 bin/echo “Hello world”,然后输出结果。
我们通过 docker 的两个参数 -i -t,让 docker 运行的容器实现"对话"的能力:
各个参数解析:
-t: 在新容器内指定一个伪终端或终端。
-i: 允许你对容器内的标准输入 (STDIN) 进行交互。
注意第三行 root@0123ce188bd8:/#
,此时我们已进入一个 ubuntu15.10 系统的容器。
我们尝试在容器中运行命令 cat /proc/version
和 ls
分别查看当前系统的版本信息和当前目录下的文件列表:
我们可以通过运行 exit
命令或者使用 CTRL+D
来退出容器。
第三行表明我们已经退出了当前的容器,返回到当前的主机中。
使用以下命令创建一个以进程方式运行的容器:
在输出中,我们没有看到期望的 “hello world”,而是一串长字符:c393a371883777f3153c764d6b3f669d07059acfd061d1db688050493d793ea6
这个长字符串叫做容器 ID
,对每个容器来说都是唯一的,我们可以通过容器 ID 来查看对应的容器发生了什么。
首先,我们需要确认容器有在运行,可以通过 docker ps
来查看:
输出详情介绍:
CONTAINER ID: 容器 ID。
IMAGE: 使用的镜像。
COMMAND: 启动容器时运行的命令。
CREATED: 容器的创建时间。
STATUS: 容器状态。
状态有7种:
PORTS: 容器的端口信息和使用的连接类型(tcp\udp)。
NAMES: 自动分配的容器名称。
在宿主主机内使用 docker logs
命令,查看容器内的标准输出:
我们使用 docker stop
命令来停止容器,并通过 docker ps
查看,容器已经停止工作:
docker 客户端非常简单,我们可以直接输入 docker 命令来查看到 Docker 客户端的所有命令选项。
可以通过命令 docker command --help
更深入的了解指定的 Docker 命令使用方法。
例如我们要查看 docker stats
指令的具体使用方法:
如果我们本地没有 ubuntu 镜像,我们可以使用 docker pull 命令来载入 ubuntu 镜像:
docker pull ubuntu
以下命令使用 ubuntu 镜像启动一个容器,参数为以命令行模式进入该容器(与上一章一样):
docker run -it ubuntu /bin/bash
要退出终端,直接输入 exit:
exit
查看所有的容器命令如下:
docker ps -a
docker start b750bbbcfd88
在大部分的场景下,我们希望 docker 的服务是在后台运行的,我们可以通过 -d 指定容器的运行模式。
docker run -itd --name ubuntu-test ubuntu /bin/bash
注: 加了 -d 参数默认不会进入容器,想要进入容器需要使用指令 docker exec。
停止容器的命令如下:
docker stop <容器 ID>
docker restart <容器 ID>
在使用 -d 参数时,容器启动后会进入后台。此时想要进入容器,可以通过以下指令进入:
attach 命令
下面演示了使用 docker attach 命令:
docker attach <容器 ID>
exec 命令
下面演示了使用 docker exec 命令:
sudo docker exec -it c393a3718837 /bin/bash
注意: 如果从这个容器退出,容器不会停止,这就是为什么推荐大家使用 docker exec
的原因。
更多参数说明请使用 docker exec --help 命令查看。
导出容器
如果要导出本地某个容器,可以使用 docker export 命令。
docker export c393a3718837 > ubuntu.tar
导出容器 c393a3718837 快照到本地文件 ubuntu.tar。
导入容器快照
可以使用 docker import 从容器快照文件中再导入为镜像,以下实例将快照文件 ubuntu.tar 导入到镜像 ubuntu:v1:
cat ubuntu.tar | sudo docker import - test/ubuntu:v1
docker import http://example.com/exampleimage.tgz example/imagerepo
删除容器
删除容器使用 docker rm
命令:
docker rm -f 1e560fca3906
docker container prune
前面我们运行的容器并没有一些什么特别的用处。接下来让我们尝试使用 docker 构建一个 web 应用程序。我们将在docker容器中运行一个 Python Flask 应用来运行一个web应用。
docker pull training/webapp # 载入镜像
docker run -d -P training/webapp python app.py
使用 docker ps
来查看我们正在运行的容器:
这里多了端口信息。
PORTS
0.0.0.0:32768->5000/tcp
Docker 开放了 5000 端口(默认 Python Flask 端口)映射到主机端口 32768 上。这时我们可以通过浏览器访问WEB应用:
我们也可以通过 -p
参数来设置不一样的端口:
docker run -d -p 5000:5000 training/webapp python app.py
docker ps
查看正在运行的容器:
容器内部的 5000 端口映射到我们本地主机的 5000 端口上。
通过 docker ps
命令可以查看到容器的端口映射,docker 还提供了另一个快捷方式 docker port
,使用 docker port
可以查看指定 (ID 或者名字)容器的某个确定端口映射到宿主机的端口号。
上面我们创建的 web 应用容器 ID 为 bf08b7f2cd89 名字为 wizardly_chandrasekhar。
可以使用 docker port bf08b7f2cd89
或 docker port wizardly_chandrasekhar
来查看容器端口的映射情况。
sudo docker port 38954191382d
5000/tcp -> 0.0.0.0:5000
5000/tcp -> :::5000
sudo docker port elastic_swirles
5000/tcp -> 0.0.0.0:32768
5000/tcp -> :::32768
docker logs [ID或者名字] 可以查看容器内部的标准输出。
-f: 让 docker logs
像使用 tail -f
一样来输出容器内部的标准输出。
从上面,我们可以看到应用程序使用的是 5000 端口并且能够查看到应用程序的访问日志。(我这没有日志信息,但是原文中的有,如下:)
我们还可以使用 docker top 来查看容器内部运行的进程:
使用 docker inspect
来查看 Docker 的底层信息。它会返回一个 JSON 文件记录着 Docker 容器的配置和状态信息。
docker stop 38954191382d
38954191382d
已经停止的容器,我们可以使用命令 docker start 来启动。(docker start 和 docker restart 有什么区别?----restart功能更多,容器运不运行都能使用)
docker start 38954191382d
38954191382d
我们可以使用 docker rm
命令来删除不需要的容器:
docker rm 38954191382d
38954191382d
删除容器时,容器必须是停止状态,否则会报如下错误:
docker rm 38954191382d
Error response from daemon: You cannot remove a running container 38954191382d0f3c93cab6a5a8792c1d3c5d259cead4c73c139030a1c56b0108. Stop the container before attempting removal or force remove
当运行容器时,使用的镜像如果在本地中不存在,docker 就会自动从 docker 镜像仓库中下载,默认是从 Docker Hub 公共镜像源下载。
下面我们来学习:
我们可以使用 docker images
来列出本地主机上的镜像。
各个选项说明:
同一仓库源可以有多个 TAG,代表这个仓库源的不同个版本,如 ubuntu 仓库源里,有 15.10、14.04 等多个不同的版本,我们使用 REPOSITORY:TAG
来定义不同的镜像。
所以,我们如果要使用版本为15.10的ubuntu系统镜像来运行容器时,命令如下:
sudo docker run -t -i ubuntu:15.10 /bin/bash
如果要使用版本为 14.04 的 ubuntu 系统镜像来运行容器时,命令如下:(这句话说的比较好,即使用镜像运行容器)
sudo docker run -t -i ubuntu:14.04 /bin/bash
如果你不指定一个镜像的版本标签,例如你只使用 ubuntu,docker 将默认使用 ubuntu:latest 镜像。
当我们在本地主机上使用一个不存在的镜像时 Docker 就会自动下载这个镜像。如果我们想预先下载这个镜像,我们可以使用 docker pull
命令来下载它。
我们可以从 Docker Hub 网站来搜索镜像,Docker Hub 网址为:https://hub.docker.com/
我们也可以使用 docker search 命令来搜索镜像。比如我们需要一个 httpd 的镜像来作为我们的 web 服务。我们可以通过 docker search 命令搜索 httpd 来寻找适合我们的镜像。
docker search httpd
我们决定使用上图中的 httpd 官方版本的镜像,使用命令 docker pull 来下载镜像。(这个和前面讲的有点重合,就是分两步走,先下载,再运行)
docker pull httpd
docker run httpd
镜像删除使用 docker rmi
命令,比如我们删除 hello-world 镜像:
docker rmi hello-world
有可能报以下错误:
可以看到在下图中的container中,还有这一项:
可以考虑先删除这个容器,再删除镜像:
或者直接使用:
sudo docker rmi -f ubuntu:15.10
当我们从 docker 镜像仓库中下载的镜像不能满足我们的需求时,我们可以通过以下两种方式对镜像进行更改。
更新镜像之前,我们需要使用镜像来创建一个容器。
yinji@yinji:~$ sudo docker run -t -i ubuntu:15.10 /bin/bash
root@0b09b46d8320:/#
在运行的容器内使用 apt-get update
命令进行更新。
在完成操作之后,输入 exit
命令来退出这个容器。
此时 ID 为 0b09b46d8320 的容器,是按我们的需求更改的容器。我们可以通过命令 docker commit 来提交容器副本。
yinji@yinji:~$ sudo docker commit -m=“has update” -a=“yinji” 9c6063148ddb yin/ubuntu:v2
sha256:78af7b53897eba2cd54d511df3af6051a86cf7178c7ef8dad6d8d889d2e2e30e
我们可以使用 docker images
命令来查看我们的新镜像 yin/ubuntu:v2:
yinji@yinji:~$ sudo docker run -t -i yin/ubuntu:v2 /bin/bash
root@5aa504c80706:/#
我们使用命令 docker build
, 从零开始来创建一个新的镜像。为此,我们需要创建一个 Dockerfile 文件,其中包含一组指令来告诉 Docker 如何构建我们的镜像。
每一个指令都会在镜像上创建一个新的层,每一个指令的前缀都必须是大写的。
第一条 FROM
,指定使用哪个镜像源。
RUN
指令告诉 docker 在镜像内执行命令,安装了什么。。。
然后,我们使用 Dockerfile 文件,通过 docker build
命令来构建一个镜像。
使用 docker images
查看创建的镜像已经在列表中存在,镜像ID为33263c26f7fc:
我们可以使用新的镜像来创建容器:
从上面看到新镜像已经包含我们创建的用户 runoob。
我们可以使用 docker tag
命令,为镜像添加一个新的标签。
sudo docker tag 33263c26f7fc runoob/centos:dev
docker tag
镜像ID,这里是 33263c26f7fc,用户名称、镜像源名(repository name)和新的标签名(tag)。
使用 docker images
命令可以看到,ID为33263c26f7fc的镜像多了一个标签。
仓库(Repository)是集中存放镜像的地方。以下介绍一下 Docker Hub。当然不止 docker hub,只是远程的服务商不一样,操作都是一样的。
目前 Docker 官方维护了一个公共仓库 Docker Hub。
大部分需求都可以通过在 Docker Hub 中直接下载镜像来实现。
在 https://hub.docker.com 免费注册一个 Docker 账号。
登录:
登录需要输入用户名和密码,登录成功后,我们就可以从 docker hub 上拉取自己账号下的全部镜像。
docker login
退出:
退出 docker hub 可以使用以下命令:
docker logout
你可以通过 docker search
命令来查找官方仓库中的镜像,并利用 docker pull
命令来将它下载到本地。
以 ubuntu 为关键词进行搜索:
docker search ubuntu
使用 docker pull 将官方 ubuntu 镜像下载到本地:
docker pull ubuntu
用户登录后,可以通过 docker push
命令将自己的镜像推送到 Docker Hub。
以下命令中的 username
请替换为你的 Docker 账号用户名。
$ docker tag ubuntu:18.04 username/ubuntu:18.04
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED ...
ubuntu 18.04 275d79972a86 6 days ago ...
username/ubuntu 18.04 275d79972a86 6 days ago ...
$ docker push username/ubuntu:18.04
$ docker search username/ubuntu
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
username/ubuntu
Dockerfile
是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。
这里仅讲解如何运行 Dockerfile 文件来定制一个镜像,具体 Dockerfile 文件内指令详解,将在下一节中介绍,这里你只要知道构建的流程即可。
下面以定制一个 nginx 镜像(构建好的镜像内会有一个 /usr/share/nginx/html/index.html 文件)
在一个空目录下,新建一个名为 Dockerfile 文件,并在文件内添加以下内容:
FROM nginx
RUN echo ‘这是一个本地构建的nginx镜像’ > /usr/share/nginx/html/index.html
FROM nginx
RUN echo '这是一个本地构建的nginx镜像' > /usr/share/nginx/html/index.html
FROM 和 RUN 指令的作用
FROM: 定制的镜像都是基于 FROM 的镜像,这里的 nginx 就是定制需要的基础镜像。后续的操作都是基于 nginx。
RUN: 用于执行后面跟着的命令行命令。有以下俩种格式:
shell 格式:
RUN <命令行命令>
# <命令行命令> 等同于,在终端操作的 shell 命令。
exec 格式:
RUN ["可执行文件", "参数1", "参数2"]
# 例如:
# RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php dev offline
注意:Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。例如:
FROM centos
RUN yum -y install wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN tar -xvf redis.tar.gz
以上执行会创建 3 层镜像。可简化为以下格式:
FROM centos
RUN yum -y install wget \
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
&& tar -xvf redis.tar.gz