Docker
容器简介
什么是Linux容器
Linux容器是与系统其他部分隔离开的一系列进程。它在另一个镜像中运行,并由该镜像提供支持进程所需的全部文件。容器提供的镜像包括了应用的所有依赖项,因此在开发到测试再到生产的过程中,容器都具有可移植性和一致性。
容器等同于虚拟化吗
容器不完全是虚拟化。虚拟化使得许多系统可同时在单个系统上运行,而容器可共享同一个操作系统的内核,将应用进程与系统其他部分隔离开。
这便意味着,即使是让多个操作系统在单个虚拟机监控程序上运行以实现虚拟化,也不能达到和使用容器同等的轻量级效果。Linux容器可从单个操作系统运行,在所有容器中共享该操作系统,因此应用和服务能够保持轻量级,并可以快速运行。
什么是Docker
IT软件中所说的Docker,是指容器化技术,用于支持创建和使用Linux容器。借助Docker,可将容器当作重量轻、模块化的虚拟机使用,同时还将获得高度的灵活性,从而实现对容器的高效创建、部署及复制,并能将其从一个环境顺利迁移至另一个环境。
Docker技术使用Linux内核和内核功能来分隔进行,以便各进程相互独立运行。
Docker的目标
Docker的主要目标是构建、运输、处处运行(Build, Ship and Run any App, Angwhere)
构建:做一个Docker镜像
运输:Docker pull
运行:启动一个容器
每个容器都有自己的文件系统rootfs
安装Docker
在Centos系统中,安装命令如下:
1 | #查看当前的内核版本 |
Hello World
Docker允许在容器中运行应用程序,使用docker run
命令来在容器中运行一个应用程序,输出Hello World如下:
1 | [root@localhost admin]# docker run ubuntu:15.10 /bin/echo "Hello world" |
运行交互式的容器
通过Docker的两个参数-i -t
,可以让Docker运行的容器实现交互式对话的能力:
1 | [root@localhost admin]# docker run -i -t ubuntu:15.10 /bin/bash |
后台模式启动容器
使用以下命令可以创建一个以进程方式运行的容器:
1 | [root@localhost admin]# docker run -d ubuntu:15.10 /bin/sh -c "while true; do echo hello world; sleep 1;done" |
容器ID对每个容器来说都是唯一的,可以通过容器ID来查看对应的容器发生了什么。
另外打开一个终端,用docker ps
查看容器是否进行:
1 | [root@localhost admin]# docker ps |
容器的状态有7种:
- created(已创建)
- restarting(重启中)
- running或Up(运行中)
- removing(迁移中)
- paused(暂停)
- exited(停止)
- dead(死亡)
停止容器
使用docker stop
命令可以使容器停止:
1 | docker stop 需要停止的容器ID |
Docker镜像管理
Docker镜像常用命令
根据镜像名称获取镜像centos:docker pull centos
查看当前主机镜像列表:docker image list
查找镜像:docker search 镜像名
导入镜像(docker-centos.tar.gz为镜像名):docker image load -i docker-centos.tar.gz
导出镜像centos:docker image save centos > docker-centos.tar.gz
删除镜像hello-world:docker rmi hello-world
删除镜像centos:docker image rm centos:latest
更新镜像:docker run -t -i ubuntu:15.10 /bin/bash
查看镜像的详细信息:docker image inspect centos
使用Dockerfile构建镜像
当从docker镜像仓库中下载的镜像不能满足需求时,可以通过以下两种方式对镜像进行更改:
- 从已经创建的容器中更新镜像,并提交这个镜像
- 使用Dockerfile命令来创建一个新的镜像
首先,使用命令docker build 从零开始创建一个新的镜像,为此需要创建一个Dockerfile文件,其中包含一组指令来告诉Docker如何构建镜像
1 | [root@localhost admin]# touch Dockerfile |
每一个指令都会在镜像上创建一个新的层,每一个指令的前缀都必须是大写的。
dockerfile 命令详情如下:
FROM:镜像从那里来
MAINTAINER:镜像维护者信息
RUN:构建镜像执行的命令,每一次RUN都会构建一层
CMD:容器启动的命令,如果有多个则以最后一个为准,也可以为ENTRYPOINT提供参数
VOLUME:定义数据卷,如果没有定义则使用默认
USER:指定后续执行的用户组和用户
WORKDIR:切换当前执行的工作目录
HEALTHCHECH:健康检测指令
ARG:变量属性值,但不在容器内部起作用
EXPOSE:暴露端口
ENV:变量属性值,容器内部也会起作用
ADD:添加文件,如果是压缩文件也解压
COPY:添加文件,以复制的形式
ENTRYPOINT:容器进入时执行的命令
其中,FROM指令指定只用哪个镜像源,RUN指令告诉docker在镜像内执行命令安装了什么。然后便可以使用Dockerfile 文件通过docker build 命令来构建一个镜像。
1 | [root@localhost admin]# docker build -t runoob/centos:6.7 . |
查看创建的镜像runoob/centos 是否已经存在:
1 | [root@localhost admin]# docker images |
现在可以使用新的镜像来创建容器:
1 | [root@localhost admin]# docker run -t -i runoob/centos:6.7 /bin/bash |
可以看到新镜像已经包含创建的用户runoob。
设置镜像标签
使用docker tag 命令可以为镜像添加一个新的标签:
1 | root@localhost admin]# docker tag 461a6483b47b runoob/centos:dev |
容器的日常管理
启动容器
最简单的运行一个容器:docker run nginx
使用ubuntu镜像启动一个容器,参数以命令行模式进入该容器:docker run -it ubuntu /bin/bash
(-it
是指交互式终端)
快速启动容器:docker run centos:latest /usr/bin/sleep 20
注意:容器内的第一个进程必须一直处于运行的状态,否则这个容器,就会处于退出状态!
查看正在运行的容器:docker container ls
查看容器详细信息/id:docker container inspect 容器名称/id
启动已停止运行的容器
查看所有容器(包括未运行的):docker ps -a
启动一个已停止运行的容器:docker start 容器名称/id
自命名启动一个容器:docker run --name ubuntu-test ubuntu /bin/bash
让ubuntu-test容器在后台运行:docker run -itd --name ubuntu-test ubuntu /bin/bash
停止容器:docker stop 容器名称/id
或者docker container kill 容器名称/id
重启停止的容器:docker restart 容器名称/id
进入容器
在使用-d
参数时,容器启动后会进入后台。此时想要进入容器,可以通过以下指令进入:
docker attach 容器名称/id
:此命令会退出容器终端,且会导致容器停止docker exec -it 容器名称/id /bin/bash
:(推荐使用此命令,此命令会退出容器终端,但不会导致容器的停止)
导入容器快照
可以使用docker import 从容器快照文件中再导入为镜像,如将快照文件ubuntu.tar导入到镜像test/ubuntu:v1中:
1 | cat docker /ubuntu.tar | docker import - test/ubuntu:v1 |
也可以通过指定URL或某个目录来导入,如:
1 | docker import http://example.com/exampleimage.tag example/imagerepo |
删除容器
使用docker rm 命令可删除容器:
1 | docker rm -f 容器名称/id |
清理掉所有处于终止状态的容器:
1 | docker container prune |
删除所有容器:
1 | docker rm -f `docker ps -a -q` |
使用docker构建一个web应用程序
在dockers容器中运行一个Python Flask应用来运行一个web应用:
1 | [root@localhost admin]# docker pull training/webapp |
不同指定的映射方法:
参数 | 说明 |
---|---|
-p hostPort:containerPort |
端口映射 -p 8080:80 |
-p ip:hostPort:containerPort |
配置监听地址 -p 10.0.0.100:8080:80 |
-p ip::containerPort |
随机分配端口 -p 10.0.0.100::80 |
-p hostPort:containerPort:udp |
指定协议 -p 8080:80:tcp |
-p 81:80 –p 443:443 |
指定多个 |
此时使用docker ps来查看正在运行的容器,会发现多了端口信息:
1 | [root@localhost admin]# docker ps |
从端口信息中可知,Docker开放了5000端口(默认Python Flask端口)映射到主机端口32768上,此时可以通过浏览器访问WEB应用:(路径为主机ip:32768端口)
可以通过参数-p
来设置不一样的端口,如将容器内部的5000端口映射到本地主机的5000端口上:
1 | [root@localhost admin]# docker run -d -p 5000:5000 training/webapp python app.py |
网络端口的快捷方式
使用docker port 可以查看指定(ID或名字)容器的某个确定端口映射到宿主机的端口号。
查看容器端口情况可用:docker port 容器名称/id
,如:
1 | [root@localhost admin]# docker port 743a62b49b70 |
查看WEB应用程序日志
查看容器内部的标准输出,可以查看端口信息和应用程序的访问日志:
1 | [root@localhost admin]# docker logs -f 743a62b49b70 |
检查WEB应用程序
使用docker inspect来查看Docker的底层信息,它会返回一个JSON文件记录着Docker容器的配置和状态信息:
1 | [root@localhost admin]# docker inspect 743a62b49b70 |
停止WEB应用容器
1 | [root@localhost admin]# docker stop 743a62b49b70 |
重启WEB应用容器
已经停止的容器可以使用命令docker start来启动:
1 | [root@localhost admin]# docker start 743a62b49b70 |
移除WEB应用容器
使用docker rm 命令来删除不需要的容器:
1 | #删除容器时,容器必须是停止状态,否则会报以下错误 |
Docker数据卷的管理
挂载时创建卷
挂载卷:
1 | [root@localhost admin]# docker run -d -p 80:80 -v /data:/usr/share/nginx/html nginx:latest |
在宿主机写入数据,查看:
1 | [root@localhost admin]# echo "http://www.nmtui.com" >/data/index.html |
设置共享卷,使用同一个卷启动一个新的容器:
1 | [root@localhost admin]# docker run -d -p 8080:80 -v /data:/usr/share/nginx/html nginx:latest |
查看卷列表:
1 | [root@localhost admin]# docker volume ls |
创建卷后挂载
创建一个卷:
1 | [root@localhost admin]# docker volume create |
指定卷名:
1 | [root@localhost admin]# docker volume create --name clsn |
查看卷路径:
1 | [root@localhost admin]# docker volume inspect clsn |
使用卷创建:
1 | [root@localhost admin]# docker run -d -p 9000:80 -v clsn:/usr/share/nginx/html nginx:latest |
设置卷:
1 | [root@localhost admin]# docker run -d -P --volumes-from 5f2530020849d15287b8bfd4dd2274945c0fd07078ab281a17e47bf2243ea113 nginx:latest |
查看使用的端口:
1 | [root@localhost admin]# netstat -lntup |
手动将容器保存为镜像
启动一个centos6.8的镜像:
1 | [root@localhost admin]# docker pull centos:6.8 |
启动完成后镜像进行ssh连接测试。
将容器提交为镜像:
1 | [root@localhost admin]# docker commit 4d61bc1e379d centos6-ssh |
使用新的镜像启动容器:
1 | [root@localhost admin]# docker run -d -p 1122:22 centos6-ssh:latest /usr/sbin/sshd -D |
进入到容器内,在容器里安装httpd服务:
1 | [root@localhost admin]# docker exec -it 0019e8bb7355 /bin/bash |
编写启动脚本:
1 | [root@0019e8bb7355 /]# touch init.sh |
再次提交为新的镜像:
1 | [root@localhost admin]# docker commit 0019e8bb7355 centos6-httpd |
启动镜像,做好端口映射。并在浏览器中输入宿主机的ip地址进行测试访问:
1 | [root@localhost admin]# docker run -d -p 1222:22 -p 88:88 centos6-httpd /init.sh |
Docker容器连接
容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过-p
或-P
参数来指定端口映射。下面来实现通过端口连接到一个docker容器。
网络端口映射
使用-P绑定端口号后,使用docker ps可以看到容器端口5000绑定主机端口32770
1 | [root@localhost admin]# docker run -d -p 32770:5000 training/webapp python app.py |
此外,还可以指定容器绑定的网络地址,如绑定127.0.0.1。
1 | [root@localhost admin]# docker run -d -p 127.0.0.1:5001:5000 training/webapp python app.py |
这样便可以通过访问127.0.0.1:5001来访问容器的5000端口。这里默认都是绑定tcp端口,若要绑定UDP端口,则需要在端口后面加上/udp。
Docker容器互联
端口映射并不是唯一把docker连接到另一个容器的方法。docker有一个连接系统允许将多个容器连接在一起,共享连接信息。docker连接会创建一个父子关系,其中父容器可以看到子容器的信息。
容器命名
当要创建一个容器时,docker会自动对他进行命名,此外也可以使用--name标识来命名容器。
1 | [root@localhost admin]# docker run -d -P --name runoob training/webapp python app.py |
--link参数
连接容器
使用--link
参数可以让容器之间安全的进行交互。
1 | #创建一个新的数据库容器 |
此时db容器和web容器建立了互联关系。
--link
参数的格式为--link name:alias
,其中name
是要链接的容器的名称,alias
是这个连接的别名。
此时使用docker ps
来查看容器的连接:
1 | [root@localhost admin]# docker ps |
Docker在两个互联的容器之间创建了一个安全隧道,而且不用映射他们的端口到宿主主机上、在启动db容器的时候并没有使用-p
和-P
标记,从而避免了暴露数据库端口到外部网络上的可能。
Docker通过2种方式为容器公开连接信息:
- 环境变量
- 更新
/etc/hosts
文件
使用env
命令来查看web容器的环境变量:
1 | [root@localhost admin]# docker run --rm --name web2 --link db:db training/webapp env |
除了环境变量,Docker还添加host信息到父容器的/etc/hosts
的文件。下面是父容器web的hosts文件:
1 | [root@localhost admin]# docker run -t -i --rm --link db:db training/webapp /bin/bash |
在web容器中安装ping命令来测试是否跟db容器的连通:
1 | root@5f57b7dcc730:/opt/webapp# apt-get install -yqq inetutils-ping |
用ping来测试db容器,它会解析成172.17.0.2。
注意:官方的Ubuntu镜像默认没有安装ping,因此需要自行安装。
用户可以链接多个父容器到子容器,比如可以链接多个web到db容器上。
通过局域网络连接容器
由于 centos-ssh镜像已失效,因此,上述步骤更新为如下:
创建名为t-net的网络
1
2
3
4
5
6
7
8[root@localhost admin]# docker network create -d bridge t-net
#其中-d表示网络类型,默认为bridge
# 列出当前主机下所有网络
[root@localhost admin]# docker network ls
NETWORK ID NAME DRIVER SCOPE
fee646ecddfa t-net bridge local
ebdcdb71d1ba test-net bridge local打开一个终端,基于镜像centos:7启动容器app1,并将容器app1加入到网络t-net中,进入到容器app1里:
1
2
3
4
5
6
7[root@localhost admin]# docker run -it --name app1 --network t-net centos:7
Unable to find image 'centos:7' locally
7: Pulling from library/centos
2d473b07cdd5: Pull complete
Digest: sha256:9d4bcbbb213dfd745b58be38b13b996ebb5ac315fe75711bd618426a630e0987
Status: Downloaded newer image for centos:7
[root@0ab7505ff23e /]#另外打开一个终端,基于镜像centos:7启动容器app2,并将容器app2也加入到网络t-net中,进入到容器app2里:
1
2[root@localhost admin]# docker run -it --name app2 --network t-net centos:7
[root@6a32efbb3dbe /]#在容器app1中
ping app2
,在容器app2中ping app1
(注意区分两个终端):1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18[root@0ab7505ff23e /]# ping app2
PING app2 (172.20.0.3) 56(84) bytes of data.
64 bytes from app2.t-net (172.20.0.3): icmp_seq=1 ttl=64 time=0.045 ms
64 bytes from app2.t-net (172.20.0.3): icmp_seq=2 ttl=64 time=0.064 ms
^C
--- app2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.045/0.054/0.064/0.012 ms
[root@6a32efbb3dbe /]# ping app1
PING app1 (172.20.0.2) 56(84) bytes of data.
64 bytes from app1.t-net (172.20.0.2): icmp_seq=1 ttl=64 time=0.092 ms
64 bytes from app1.t-net (172.20.0.2): icmp_seq=2 ttl=64 time=0.214 ms
64 bytes from app1.t-net (172.20.0.2): icmp_seq=3 ttl=64 time=0.077 ms
^C
--- app1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 0.077/0.127/0.214/0.062 ms以上结果则表示0丢包,容器之间能够正常通讯。
Docker仓库管理
仓库是集中存放镜像的地方,目前Docker官方维护了一个公共仓库Docker Hub,大部分需求的镜像都可以通过在Docker Hub中直接找到。
登录和登出
若还没有Docker账号,可在 https://hub.docker.com 上免费注册一个。然后输入用户名和密码登录,登录成功后便可以从Docker hub上拉去自己账号下的全部镜像。
1 | [root@localhost admin]# docker login |
使用docker logout
命令可以登出Docker hub。
拉取镜像
使用docker search
命令可以查找官方仓库中的镜像,并利用docker pull
命令将其下载到本地,例如要下载ubuntu镜像,操作如下:
1 | [root@localhost admin]# docker search ubuntu |
推送镜像
用户登录后,可以通过docker push
命令将自己的镜像推送到Docker Hub,如:
1 | #查看目前已有的镜像 |