菜鸟教程:https://www.runoob.com/docker/docker-architecture.html
一、Docker应用场景
- Web 应用的自动化打包和发布。
- 自动化测试和持续集成、发布。
- 在服务型环境中部署和调整数据库或其他的后台应用。
- 从头编译或者扩展现有的 OpenShift 或 Cloud Foundry 平台来搭建自己的 PaaS 环境。
二、Docker 三个基本概念
- 镜像(Image):Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。
- 容器(Container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
- 仓库(Repository):仓库可看成一个代码控制中心,用来保存镜像。
三、Docker容器使用
1. 进行交互式的容器
通过 docker 的两个参数 -i -t,让 docker 运行的容器实现"对话"的能力:
runoob@runoob:~$ docker run -i -t ubuntu:15.10 /bin/bash
root@0123ce188bd8:/#
参数解析:
- -t: 在新容器内指定一个伪终端或终端。
- -i: 允许你对容器内的标准输入 (STDIN) 进行交互。
2. 启动容器(后台模式)
docker run -d ubuntu:15.10 /bin/sh -c "while true; do echo hello world; sleep 1; done"
2b1b7a428627c51ab8810d541d759f072b4fc75487eed05812646b8534a2fe63
3. 查看容器运行情况
docker ps
输出详情介绍:
CONTAINER ID: 容器 ID。
IMAGE: 使用的镜像。
COMMAND: 启动容器时运行的命令。
CREATED: 容器的创建时间。
STATUS: 容器状态。
PORTS: 容器的端口信息和使用的连接类型(tcp\udp)。
NAMES: 自动分配的容器名称。
4. 查看容器内的标准输出
docker logs 2b1b7a428627
#docker logs amazing_cori
5. 停止容器
docker stop 2b1b7a428627
#docker stop amazing_cori
6. 容器使用-获取镜像
#通过pull命令载入ubuntu镜像
docker pull ubuntu
7. 容器使用-启动容器
#使用 ubuntu 镜像启动一个容器,参数为以命令行模式进入该容器
docker run -it ubuntu /bin/bash
#退出终端:exit
8. 启动已停止运行的容器
#查看所有的容器命令:
docker ps -a
#使用 docker start 启动一个已停止的容器(通过status判断容器状态):
docker start b750bbbcfd88
9. 后台运行
#大部分的场景下,我们希望 docker 的服务是在后台运行的,我们可以过 -d 指定容器的运行模式
docker run -itd --name ubuntu-test ubuntu /bin/bash
#注:加了 -d 参数默认不会进入容器,想要进入容器需要使用指令 docker exec
10. 停止一个容器
docker stop <容器 ID>
#停止的容器可以通过 docker restart 重启:
docker restart <容器 ID>
11. 进入容器
使用 -d 参数时,容器启动后会进入后台。此时想要进入容器,可以通过以下指令进入
- docker attach
- docker exec:推荐使用 docker exec 命令,因为此退出容器终端,不会导致容器的停止。
#attach 命令
docker attach 1e560fca3906
#注:如果从这个容器退出,会导致容器的停止。
#exec 命令
docker exec -it 243c32535da7 /bin/bash
#注:如果从这个容器退出,不会导致容器的停止。
12. 导出和导入容器
导出容器
如果要导出本地某个容器,可以使用 docker export 命令
#导出容器 1e560fca3906 快照到本地文件 ubuntu.tar
#注意:1e560fca3906为container id,是容器的ID,不是iamge镜像ID
docker export 1e560fca3906 > ubuntu.tar
导入容器快照
可以使用 docker import 从容器快照文件中再导入为镜像,以下实例将快照文件 ubuntu.tar 导入到镜像 test/ubuntu:v1:
cat docker/ubuntu.tar | docker import - test/ubuntu:v1
#也可以通过指定 URL 或者某个目录来导入
docker import http://example.com/exampleimage.tgz example/imagerepo
13. 删除容器
删除容器使用 docker rm 命令
docker rm -f 1e560fca3906
#下面的命令可以清理掉所有处于终止状态的容器
docker container prune
14. 运行一个 web 应用
docker pull training/webapp # 载入镜像
docker run -d -P training/webapp python app.py
参数说明:
- -d:让容器在后台运行。
- -P:将容器内部使用的网络端口随机映射到我们使用的主机上。
#可以通过 -p 参数来设置不一样的端口:
docker run -d -p 5000:5000 training/webapp python app.py
#容器内部的 5000 端口映射到我们本地主机的 5000 端口上
15. 网络端口的快捷方式
docker 还提供了另一个快捷方式 docker port,使用 docker port 可以查看指定 (ID 或者名字)容器的某个确定端口映射到宿主机的端口号。
docker port bf08b7f2cd89
#输出:5000/tcp -> 0.0.0.0:5000
15. 查看 WEB 应用程序日志
#docker logs [ID或者名字] 可以查看容器内部的标准输出。
docker logs -f bf08b7f2cd89
#-f: 让 docker logs 像使用 tail -f 一样来输出容器内部的标准输出。
四、Docker镜像使用
当运行容器时,使用的镜像如果在本地中不存在,docker 就会自动从 docker 镜像仓库中下载,默认是从 Docker Hub 公共镜像源下载。
1. 列出镜像列表
docker images
选项说明
- REPOSITORY:表示镜像的仓库源
- TAG:镜像的标签
- IMAGE ID:镜像ID
- CREATED:镜像创建时间
- SIZE:镜像大小
#使用版本为15.10的ubuntu系统镜像来运行容器
docker run -t -i ubuntu:15.10 /bin/bash
2. 获取一个新的镜像
#例如获取ubuntu 13.10版本镜像
docker pull ubuntu:13.10
3. 查找镜像
从 Docker Hub 网站来搜索镜像,Docker Hub 网址为: https://hub.docker.com/
也可以使用 docker search 命令来搜索镜像
docker search httpd
#列说明
# NAME: 镜像仓库源的名称
# DESCRIPTION: 镜像的描述
# OFFICIAL: 是否 docker 官方发布
# stars: 类似 Github 里面的 star,表示点赞、喜欢的意思。
# AUTOMATED: 自动构建。
4. 拖取镜像
#docker pull 来下载镜像
docker pull httpd
#载完成后,使用这个镜像
docker run httpd
5. 删除镜像
#镜像删除使用 docker rmi 命令
docker rmi hello-world
6. 创建镜像
当我们从 docker 镜像仓库中下载的镜像不能满足我们的需求时,我们可以通过以下两种方式对镜像进行更改。
- 从已经创建的容器中更新镜像,并且提交这个镜像
- 使用 Dockerfile 指令来创建一个新的镜像
更新镜像
更新镜像之前,我们需要使用镜像来创建一个容器
runoob@runoob:~$ docker run -t -i ubuntu:15.10 /bin/bash
root@e218edb10161:/#
在运行的容器内使用 apt-get update 命令进行更新。
完成操作之后,输入 exit 命令来退出这个容器。
通过命令 docker commit 来提交容器副本
docker commit -m="has update" -a="runoob" e218edb10161 runoob/ubuntu:v2
参数说明:
- -m: 提交的描述信息
- -a: 指定镜像作者
- e218edb10161:容器 ID
- runoob/ubuntu:v2: 指定要创建的目标镜像名
使用 docker images 命令来查看我们的新镜像 runoob/ubuntu:v2
docker images
使用新镜像 runoob/ubuntu 来启动一个容器
runoob@runoob:~$ docker run -t -i runoob/ubuntu:v2 /bin/bash
root@1a9fbdeb5da3:/#
7. 构建镜像
使用命令 docker build , 从零开始来创建一个新的镜像。创建一个 Dockerfile 文件。
runoob@runoob:~$ cat Dockerfile
FROM centos:6.7
MAINTAINER Fisher "fisher@sudops.com"
RUN /bin/echo 'root:123456' |chpasswd
RUN useradd runoob
RUN /bin/echo 'runoob:123456' |chpasswd
RUN /bin/echo -e "LANG=\"en_US.UTF-8\"" >/etc/default/local
EXPOSE 22
EXPOSE 80
CMD /usr/sbin/sshd -D
# 构建镜像
# 第一条FROM,指定使用哪个镜像源
# RUN 指令告诉docker 在镜像内执行命令
# 然后,使用 Dockerfile 文件,通过 docker build 构建新的镜像
runoob@runoob:~$ docker build -t runoob/centos:6.7 .
Sending build context to Docker daemon 17.92 kB
Step 1 : FROM centos:6.7
---> d95b5ca17cc3
Step 2 : MAINTAINER Fisher "fisher@sudops.com"
---> Using cache
---> 0c92299c6f03
Step 3 : RUN /bin/echo 'root:123456' |chpasswd
---> Using cache
---> 0397ce2fbd0a
Step 4 : RUN useradd runoob
......
参数说明:
- -t :指定要创建的目标镜像名
- . :Dockerfile 文件所在目录,可以指定Dockerfile 的绝对路径
使用docker images 查看创建的镜像已经在列表中存在。
docker images
#可以使用新的镜像来创建容器
8. 设置镜像标签
可以使用 docker tag 命令,为镜像添加一个新的标签。
runoob@runoob:~$ docker tag 860c279d2fec runoob/centos:dev
#docker tag 镜像ID,这里是 860c279d2fec ,用户名称、镜像源名(repository name)和新的标签名(tag)
五、Docker 容器连接
1. 网络端口映射
以创建一个python 应用的容器为例
runoob@runoob:~$ docker run -d -P training/webapp python app.py
fce072cc88cee71b1cdceb57c2821d054a4a59f67da6b416fceb5593f059fc6d
runoob@runoob:~$ docker ps
CONTAINER ID IMAGE COMMAND ... PORTS NAMES
fce072cc88ce training/webapp "python app.py" ... 0.0.0.0:32768->5000/tcp grave_hopper
runoob@runoob:~$ docker run -d -p 5000:5000 training/webapp python app.py
33e4523d30aaf0258915c368e66e03b49535de0ef20317d3f639d40222ba6bc0
runoob@runoob:~$ docker ps
CONTAINER ID IMAGE COMMAND ... PORTS NAMES
33e4523d30aa training/webapp "python app.py" ... 0.0.0.0:5000->5000/tcp berserk_bartik
fce072cc88ce training/webapp "python app.py" ... 0.0.0.0:32768->5000/tcp grave_hopper
#也可以指定容器绑定的网络地址,比如绑定 127.0.0.1
runoob@runoob:~$ docker run -d -p 127.0.0.1:5001:5000 training/webapp python app.py
95c6ceef88ca3e71eaf303c2833fd6701d8d1b2572b5613b5a932dfdfe8a857c
参数-P和-p区别:
- -P :是容器内部端口随机映射到主机的高端口。
- -p : 是容器内部端口绑定到指定的主机端口。
docker port 命令可以让我们快捷地查看端口的绑定情况
runoob@runoob:~$ docker port adoring_stonebraker 5000
127.0.0.1:5001
2. Docker 容器互联
端口映射并不是唯一把 docker 连接到另一个容器的方法。
docker 有一个连接系统允许将多个容器连接在一起,共享连接信息。
docker 连接会创建一个父子关系,其中父容器可以看到子容器的信息。
容器命名
创建一个容器的时候,docker 会自动对它进行命名。另外,我们也可以使用 --name 标识来命名容器,例如:
docker run -d -P --name runoob training/webapp python app.py
新建网络
docker network create -d bridge test-net
参数说明:
-d:参数指定 Docker 网络类型,有 bridge、overlay。
连接容器
运行一个容器并连接到新建的 test-net 网络:
docker run -itd --name test1 --network test-net ubuntu /bin/bash
打开新的终端,再运行一个容器并加入到 test-net 网络:
docker run -itd --name test2 --network test-net ubuntu /bin/bash
通过 ping 来证明 test1 容器和 test2 容器建立了互联关系。
3. 配置 DNS
在宿主机的 /etc/docker/daemon.json 文件中增加以下内容来设置全部容器的 DNS:
{
"dns" : [
"114.114.114.114",
"8.8.8.8"
]
}
六、Docker 仓库管理
1. 登录和退出
docker login
docker logout
#docker search 命令来查找官方仓库中的镜像,并利用 docker pull 命令来将它下载到本地
#以 ubuntu 为关键词进行搜索:
docker search ubuntu
#使用 docker pull 将官方 ubuntu 镜像下载到本地:
docker pull ubuntu
2. 推送镜像
用户登录后,可以通过 docker push 命令将自己的镜像推送到 Docker Hub。
$ 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
七、Docker Dockerfile
1. 使用 Dockerfile 定制镜像
Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。
以定制一个 nginx 镜像为例:
#在一个空目录下,新建一个名为 Dockerfile 文件
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 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 install wget \
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
&& tar -xvf redis.tar.gz
#以 && 符号连接命令,这样执行后,只会创建 1 层镜像。
2. 开始构建镜像
#通过目录下的 Dockerfile 构建一个 nginx:test(镜像名称:镜像标签)
docker build -t nginx:test .
#注:最后的 . 代表本次执行的上下文路径
3. 上下文路径
上下文路径,是指 docker 在构建镜像,有时候想要使用到本机的文件(比如复制),docker build 命令得知这个路径后,会将路径下的所有内容打包。
如果未说明最后一个参数,那么默认上下文路径就是 Dockerfile 所在的位置。
注:上下文路径下不要放无用的文件,因为会一起打包发送给 docker 引擎,如果文件过多会造成过程缓慢。
4. 指令详解
COPY
复制指令,从上下文目录中复制文件或者目录到容器里指定路径。
COPY hom* /mydir/
COPY hom?.txt /mydir/
#容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。
ADD
ADD 指令和 COPY 的使用格式一致(同样需求下,官方推荐使用 COPY)。
CMD
类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:
- CMD 在docker run 时运行。
- RUN 是在 docker build。
作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。
注意:如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。
ENTRYPOINT
类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖。
但是, 如果运行 docker run 时使用了 --entrypoint 选项,此选项的参数可当作要运行的程序覆盖 ENTRYPOINT 指令指定的程序。
使用案例:
假设已通过 Dockerfile 构建了 nginx:test 镜像:
FROM nginx
ENTRYPOINT ["nginx", "-c"] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参
- 不传参运行
docker run nginx:test
容器内会默认运行以下命令,启动主进程。
nginx -c /etc/nginx/nginx.conf
- 传参运行
docker run nginx:test -c /etc/nginx/new.conf
容器内会默认运行以下命令,启动主进程(/etc/nginx/new.conf:假设容器内已有此文件)
nginx -c /etc/nginx/new.conf
ENV
设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。
ENV NODE_VERSION 7.2.0
RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
&& curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc"
ARG
构建参数,与 ENV 作用一至。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。
VOLUME
定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。
EXPOSE
仅仅只是声明端口。
WORKDIR
指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。
USER
用于指定执行后续命令的用户和用户组
HEALTHCHECK
用于指定某个程序或者指令来监控 docker 容器服务的运行状态。
ONBUILD
用于延迟构建命令的执行。
Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜像的过程中不会执行。
当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这是执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令。
八、Docker Compose
1. Compose 简介
Compose 是用于定义和运行多容器 Docker 应用程序的工具。使用 YML 文件来配置应用程序需要的所有服务,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。
Compose 使用的三个步骤:
- 使用 Dockerfile 定义应用程序的环境。
- 使用 docker-compose.yml 定义构成应用程序的服务,这样它们可以在隔离环境中一起运行。
- 最后,执行 docker-compose up 命令来启动并运行整个应用程序。
2. Compose 安装
#下载 Docker Compose 的当前稳定版本
sudo curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
#可执行权限应用于二进制文件:
sudo chmod +x /usr/local/bin/docker-compose
#创建软链:
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
3. 创建 docker-compose.yml
# yaml 配置
version: '3'
services:
web:
build: .
ports:
- "5000:5000"
redis:
image: "redis:alpine"
该 Compose 文件定义了两个服务:web 和 redis。
- web:该 web 服务使用从 Dockerfile 当前目录中构建的镜像。然后,它将容器和主机绑定到暴露的端口 5000。此示例服务使用 Flask Web 服务器的默认端口 5000 。
- redis:该 redis 服务使用 Docker Hub 的公共 Redis 映像。
4. 使用 Compose 命令构建和运行应用
docker-compose up
#在后台执行该服务可以加上 -d 参数:
docker-compose up -d
九、Docker Machine
Docker Machine 是一种可以让您在虚拟主机上安装 Docker 的工具,并可以使用 docker-machine 命令来管理主机。
Docker Machine 也可以集中管理所有的 docker 主机,比如快速的给 100 台服务器安装上 docker。
1. 列出可用的机器
docker-machine ls
2. 创建机器
docker-machine create --driver virtualbox test
3. 查看机器的 ip
docker-machine ip test
4. 停止机器
docker-machine stop test
5. 启动机器
docker-machine start test
6. 进入机器
docker-machine ssh test
十、Swarm 集群管理
Docker Swarm 是 Docker 的集群管理工具。它将 Docker 主机池转变为单个虚拟 Docker 主机。 Docker Swarm 提供了标准的 Docker API,所有任何已经与 Docker 守护程序通信的工具都可以使用 Swarm 轻松地扩展到多个主机。
1. 创建 swarm 集群管理节点(manager)
docker-machine create -d virtualbox swarm-manager
#初始化 swarm 集群,进行初始化的这台机器,就是集群的管理节点。
docker-machine ssh swarm-manager
docker swarm init --advertise-addr 192.168.99.107 #这里的 IP 为创建机器时分配的 ip。
2. 查看集群信息
docker info