一、基础命令
1.运行一个镜像
[root@bogon ~]# docker run debian echo "Hello World"
Unable to find image 'debian:latest' locally
latest: Pulling from library/debian
3e17c6eae66c: Pull complete
Digest: sha256:2e43e863a4ab6e53caf87a37d01d8c144cdcb732ad1b944fcf45cbfd7248a02a
Status: Downloaded newer image for debian:latest
Hello World
提供一个容器中的shell
[root@bogon ~]# docker run -i -t debian /bin/bash
root@1bd73131a553:/# echo "Hello from Container-land!"
Hello from Container-land!
root@1bd73131a553:/# exit
exit
2.运行案例分析
1)docker pull
Docker Daemon从Docker Registry下载指定的容器镜像,并将镜像储存在本地Graph中。
流程分析:
A.Docker Client处理用户发起的docker pull命令,解析完请求以及参数后,发送一个HTTP请求给Docker Server,HTTP请求方法为POST,请求URI为“/images/create?”+“xxx”;
B.Docker Server接收以上HTTP请求,并交给mux.Router,通过URL以及请求方式类型来确定执行该请求的具体handler;
C.mux.Router将请求路由分发至相应的handler;
D.在PostImageCreate这个handler中,创建并初始化一个名为“pull”的Job,之后触发执行该Job;
E.这个Job在执行过程中执行pullRepository操作,即从Docker Registry中下载相应的一个或多个Docker镜像;
F.这个Job将下载的Docker镜像交给graphdriver管理;
G.graphdriver负责存储Docker镜像,一方面将镜像存储至本地文件系统中,另一方面为镜像创建对象,由Docker Daemon统一管理。
2)docker run
创建一个全新的Docker容器,并在容器中运行指定命令。
- 创建Docker容器对象,并为容器准备所需的rootfs;
- 创建容器的运行环境,运行用户指令;
流程分析:
A.Docker Client处理用户发起的docker run命令,解析完请求与参数之后,向Docker Server发送一个HTTP请求,HTTP请求方式为POST,请求URL为“/containers/create?”+“xxx”;(创建容器对象而非实际容器)
B.Docker Server接收以上HTTP请求,并交给mux.Router,通过URL以及请求方式类型来确定执行该请求的具体handler;
C.mux.Router将请求路由分发至相应的handler;
D.在PostContainersCreate这个handler中,创建并初始化一个名为“create”的Job,之后触发执行该Job;
E.这个Job在执行过程中执行Container.Create操作,该操作需要获取容器镜像来为Docker容器准备rootfs,通过graphdriver完成;
F.graphdriver从Graph中获取创建Docker容器rootfs所需要的所有镜像;
G.graphdriver将rootfs的所有镜像通过某种联合文件系统的方式加载至Docker容器指定的文件目录中;
H.若以上操作正常执行,没有返回错误或异常,则Docker Client收到Docker Server返回状态后,发起二次HTTP请求,URL为“/containers/”+container_ID+“/start”;(实现物理容器运行)
I.Docker Server接收以上HTTP请求,并交给mux.Router,通过URL以及请求方式类型来确定执行该请求的具体handler;
J.mux.Router将请求路由分发至相应的handler;
K.在PostContainersStart这个handler中,创建并初始化一个名为“start”的Job,之后触发执行该Job;
L.这个Job执行需要完成一系列与Docker容器相关的资源配置工作;
M.networkdriver为指定的Docker容器分配网络资源,防火墙规则
N.返回名为“start”的Job,执行完一些辅助操作后,Job开始执行用户指令,调用execdriver;
O.execdriver被调用,开始初始化Docker容器内部的运行环境,如命名空间、资源控制与隔离,以及用户命令的执行,相应的操作转交至libcontainer来完成;
P.libcontainer被调用,完成Docker容器内部的运行环境初始化,并最终执行用户要求启动的命令。
3.常用命令解析
1)启动容器
[root@bogon ~]# docker run -h CONTAINER -i -t debian /bin/bash
root@CONTAINER:/#
-h 设定新的主机名(hostname)
2)查看容器
为了测试,我将容器搞坏了
root@CONTAINER:/# mv /bin /basket
root@CONTAINER:/# ls
bash: ls: command not found
现在查看状态
[root@bogon ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8f64d43a4e26 debian "/bin/bash" 2 minutes ago Up 2 minutes competent_euclid
通过NAMES获取容器信息
[root@bogon ~]# docker inspect competent_euclid
[
{
"Id": "8f64d43a4e26dbe29626f82feb7aafc759fe805699f0f014aaf3b2be82790c82",
"Created": "2017-10-23T13:47:20.594553293Z",
"Path": "/bin/bash",
"Args": [],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 2662,
"ExitCode": 0,
"Error": "",
"StartedAt": "2017-10-23T13:47:20.855942407Z",
"FinishedAt": "0001-01-01T00:00:00Z"
...省略部分
过滤相关内容
[root@bogon ~]# docker inspect competent_euclid |grep IPAddress
"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.2",
"IPAddress": "172.17.0.2",
[root@bogon ~]# docker inspect --format {{ .NetworkSettings.IPAddress }} competent_euclid
Template parsing error: template: :1: unexpected unclosed action in command
<注意:括号内不要有空格>
[root@bogon ~]# docker inspect --format {{.NetworkSettings.IPAddress}} competent_euclid
172.17.0.2
容器内的改变
[root@bogon ~]# docker diff competent_euclid
A /basket (A表示新增文件)
A /basket/vdir
A /basket/chgrp
A /basket/fgrep
A /basket/mv
A /basket/pidof
A /basket/rbash
...省略部分
D /bin (D表示被删除的文件)
容器执行日志
[root@bogon ~]# docker logs competent_euclid
root@CONTAINER:/# mv /bin /basket
root@CONTAINER:/# ls
bash: ls: command not found
3)删除容器
查看全部容器(包括已停止的)
[root@bogon ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8f64d43a4e26 debian "/bin/bash" 11 minutes ago Exited (127) 23 seconds ago competent_euclid
1bd73131a553 debian "/bin/bash" About an hour ago Exited (0) About an hour ago cranky_austin
重新启动容器
docker start
删除容器
[root@bogon ~]# docker rm competent_euclid
competent_euclid
清理所有已停止的容器
[root@bogon ~]# docker ps -aq -f status=exited
1bd73131a553
69914367d6b4
74ef7227163a
5a1754f8433f
944c67e9d101
e0294c4a650a
[root@bogon ~]# docker rm -v $(docker ps -aq -f status=exited)
1bd73131a553
69914367d6b4
74ef7227163a
5a1754f8433f
944c67e9d101
e0294c4a650a
-v 当所有由Docker管理的数据卷已经没有和任何容器关联时,一律删除
[root@bogon ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
36c220e77949 busybox "/bin/ping webapp" 3 hours ago Created destination
4)创建一个全新的容器流程
[root@bogon ~]# docker run -it --name cowsay --hostname cowsay debian bash
root@cowsay:/# apt-get update
...
root@cowsay:/# apt-get install -y cowsay fortune
root@cowsay:/# /usr/games/fortune | /usr/games/cowsay
root@cowsay:/# exit
把容器转成镜像
[root@bogon ~]# docker commit cowsay test/cowsayimage
[root@bogon ~]# docker run test/cowsayimage /usr/games/cowsay "Moo"
二、通过Dockerfile创建镜像
1.Dockerfile
[root@bogon ~]# cat Dockerfile
FROM debian:wheezy
RUN apt-get update && apt-get install -y cowsay fortune
2.镜像、容器和联合文件系统之间的关系
联合文件系统(联合挂载)—允许多个文件系统叠加,并表现为一个单一的文件系统;若有两个文件的路径完全相同,则最后挂载的文件覆盖之前的;
Docker支持多种不同的文件系统,AUFS、Overlay、devicemapper、BTRFS、ZFS;
[root@bogon ~]# docker info
Containers: 2
Running: 0
Paused: 0
Stopped: 2
Images: 12
Server Version: 17.09.0-ce
Storage Driver: overlay <<<<<<<<
Backing Filesystem: xfs
Supports d_type: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Docker镜像由多个不同的层(layer)组成,每一层都是一个只读的文件系统;
Dockerfile里的每一个指令都会创建一个新的层,这个层位于前一个层之上;
当一个镜像被转化成容器时,Docker引擎会在镜像之上添加一个处于最上层的可读写文件系统。(尽量将指令写在一行来较少层的数量)
容器可处于:已创建(created)、重启中(restarting)、运行中(running)、已暂停(paused)、已退出(exited)
3.ENTRYPOINT
指定一个可执行文件,处理传给docker run的参数。
[root@bogon ~]# cat Dockerfile
FROM debian:wheezy
RUN apt-get update && apt-get install -y cowsay fortune
COPY entrypoint.sh /
ENTRYPOINT ["/entrypoint.sh"]
[root@bogon ~]# cat entrypoint.sh
#!/bin/bash
if [ $# -eq 0 ];then
/usr/games/fortune | /usr/games/cowsay
else
/usr/games/cowsay "$0"
fi
[root@bogon ~]# docker build -t test/cowsay-dockerfile .
[root@bogon ~]# docker run test/cowsay-dockerfile "Moo"
4.上传镜像
[root@bogon ~]# cat Dockerfile
FROM debian:wheezy
MAINTAINER hdlptz <hdlptz@163.com>
RUN apt-get update && apt-get install -y cowsay fortune
COPY entrypoint.sh /
ENTRYPOINT ["/entrypoint.sh"]
[root@bogon ~]# docker build -t hdlptz/cowsay:stable
[root@bogon ~]# docker push hdlptz/cowsay:stable
5.镜像的命名空间
由镜像名称判断:
- 以字符串和“/”开头,如hdlptz/revealjs,属于用户命名空间(user namespace)
- 如debian或ubuntu的名称,不包含前缀或/,属于根命名空间(root namespace)
- 以主机名或IP开头的名称,代表该镜像来自第三方的寄存服务,包括公司自己搭建的寄存服务
三、Redis镜像实例
[root@bogon ~]# docker pull redis
Using default tag: latest
latest: Pulling from library/redis
d13d02fa248d: Pull complete
a1846f364e39: Pull complete
dba901efed8c: Pull complete
b54b43b9d049: Pull complete
b5b9e2d5e9c6: Pull complete
7058d282fa00: Pull complete
Digest: sha256:07e7b6cb753f8d06a894e22af30f94e04844461ab6cb002c688841873e5e5116
Status: Downloaded newer image for redis:latest
[root@bogon ~]# docker run -v /data test/webserver
[root@bogon ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hubuser/webapp latest cbe52807fcad 7 hours ago 362MB
redis latest 1fb7b6c8c0d0 13 days ago 107MB
debian latest 874e27b628fd 13 days ago 100MB
ubuntu 14.04 dea1945146b9 5 weeks ago 188MB
busybox latest 54511612f1c4 5 weeks ago 1.13MB
[root@bogon ~]# docker run --name myredis -d redis
d07dd579ee128a9500b81507764edbcf81aef3281a22eee22fe04c74163c6986
[root@bogon ~]# docker run --rm -it --link myredis:redis redis /bin/bash
root@cbe4f668dba7:/data# redis-cli -h redis -p 6379
redis:6379> ping
PONG
redis:6379> set "docker" 1234
OK
redis:6379> get "docker"
"1234"
redis:6379> exit
root@cbe4f668dba7:/data# exit
exit
[root@bogon ~]# docker run --rm --volumes-from myredis -v $(pwd)/backup:/backup
debian cp /data/dump.rdb /backup/
[root@bogon ~]# docker stop myredis
[root@bogon ~]# docker rm -v myredis
[root@bogon ~]# docker rm $(docker ps -aq)