docker容器基础

容器的介绍

容器是一种基础工具,泛指任何可以用于容纳其他物品的工具,可以部分或完全封闭,被用于容纳、存储、运输物品;物体可以被放置在容器中,而容器则可以保护内容物。

名称挂载点

Mount:挂载点

UTS:主机名与域名

IPC:信息量、消息队列和共享内存

PID:进程号

Network:网络设备、网络栈、端口号

user:用户和组

docker的概念

Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源。Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。

在 LXC 的基础上 Docker 进行了进一步的封装,就是用户创建容器的一个工具。让用户不需要去关心容器的管理,使得操作更为简便。用户操作 Docker 的容器就像操作一个快速轻量级的虚拟机一样简单。

LXC: LinuX Container  (Linux容器)

chroot,根切换;
namespaces:名称空间
CGroups:控制组

简单使用

lxc-checkconfig:
检查系统环境是否满足容器使用要求;
lxc-create:创建lxc容器;
lxc-create -n NAME -t TEMPLATE_NAME
lxc-start:启动容器;
lxc-start -n NAME -d

Docker 容器的启动可以在秒级实现,这相比传统的虚拟机方式要快得多
Docker 对系统资源的利用率很高,一台主机上可以同时运行数千个 Docker 容器
更快速的交付和部署、更轻松的迁移和扩展

docker的安装

 Centos 官网http://vault.centos.org/查找与本机系统所匹配的源

# cd /etc/yum.repos.d/
# vim base.repo 
[base]
name=base
baseurl=file:///mnt/cd
gpgcheck=0

[epel]
name=epel
baseurl=https://mirrors.aliyun.com/epel/7Server/x86_64/
gpgcheck=0

[extras]
name=extras
baseurl=http://vault.centos.org/7.4.1708/extras/x86_64/
gpgcheck=0

阿里云官网:https://opsx.alibaba.com/上查找配置docker源

[docker]
name=docker
https://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/stable/
gpgcheck=0
#yum install docker-ce -y #安装包
添加镜像加速器
#mkdir -p /etc/docker/
vim /etc/docker/daemon.json
{
 "registry-mirrors": ["https://registry.docker-cn.com"]
}   #(添加此行)官网的镜像加速器,还可以使用阿里云的镜像加速器

#systemctl start docker #启动服务
# ps aux | grep docker-ce #查看进程

docker命令

Containers:管理容器

Images:管理镜像、映射

#docker version  #查看版本信息
#docker info  #查看详细信息;运行的容器个数;暂停的个数;镜像个数等

容器的管理

docker  search:#搜寻官网上的docker镜像
  例:#docker search nginx  #搜寻nginx的镜像
docker image  pull:#从官网上下载docker镜像
  例:#docker pull nginx   #下载搜索的nginx镜像
docker image list :#列出本地所有的docker镜像
#docker image list nginx    #只列出本地nginx版本的镜像
docker image rm   #删除下载下来的本地镜像
   例:#docker image rm nginx:1.14-alpine  #镜像+标签

docker restart  #重新启动docker容器

docker stop     #停止docker容器

docker kill    #强行停止docker容器

docker rm       #删除创建的容器

容器的创建

 注:如果本地没有镜像文件,启动时会自动到官网下载

docker create:(创建docker容器)
例:#docker create -it  --name b1 busybox:latest  #只是busybox需要添加-it的命令来创建
#docker create --name b2 nginx   #其他容器的创建
docker start #启动docker容器
#docker start
-i -a b1 #( b1:为创建容器的自定义的名称;-i -a也只是busybox镜像启动的所添加的选项) #docker start b1 #其他容器的启动 docker run #直接创建运行docker容器;如果本地没人镜像文件docker会自动去官网上查询并下载。 例1 :#docker run --name b1 -it busybox:latest #b1为自定义的容器名称;-it 为开启交互式界面,既打开容器的界面,也busybox:latest 镜像
例2: #docker run --name web1
-d nginx #运行nginx的镜像;-d 不要运行在后台,因为此docker容器只有一个程序;如果运行在后台,容器上没有运行的程序,默认会终止此容器

例 :docker run –name red1 -d redis:4-alpine (创建一个redis镜像,版本号不指定,默认安装的是latest,由于本地没有镜像,会去官网上自动去下载)

QQ截图20180801112301

# docker image ls   #查看下载下来的镜像存放在本地
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
busybox             latest              e1ddd7948a1c        14 hours ago        1.16MB
nginx               latest              c82521676580        7 days ago          109MB
redis               latest              f06a5773f01e        2 weeks ago         83.4MB
# docker container ls -a   #查看处于停止状态的daoke容器
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
98efd5c32689        redis               "docker-entrypoint.s…"   2 minutes ago       Up 2 minutes        6379/tcp            red1
e09e962eab28        nginx               "nginx -g 'daemon of…"   5 minutes ago       Up 5 minutes        80/tcp              web1
de0348a6f872        busybox:latest      "sh"                     31 minutes ago      Created                                 b2
7914fa9050a1        nginx               "nginx -g 'daemon of…"   32 minutes ago      Created                                 b1

交互式启动一个容器

-i:–interactive,交互式;
-t:Allocate a pseudo-TTY
#docker exec -it red1 /bin/sh     #以交互式的方式进入到已经开启的容器里面去
#docker ps | docker container  |  ps docker container ls   # 列出容器的详细信息

Docker镜像

docker的镜像文件官网 https://hub.docker.com/ 

# docker pull nginx:1.14-alpine   #后面为版本信息,在官网啊地址上搜寻的结果
#docker pull nginx  #后不加版本信息下载下来的是默认标签latest(最新)版本
#docker image list  #查看下载的镜像
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest c82521676580 7 days ago 109MB

Docker镜像的原理及组成

Docker镜像含有启动容器所需要的文件系统及其内容,因此, 其用于创建并启动docker容器 。

结构

采用分层构建机制,最底层为bootfs,其之为rootfs

bootfs:用于系统引导的文件系统,包括bootloader和kernel,容器启动完 成后会被卸载以节约内存资源;

rootfs:位于bootfs之上,表现为docker容器的根文件系统;

传统模式中,系统启动之时,内核挂载rootfs时会首先将其挂载为“只读”模式, 完整性自检完成后将其重新挂载为读写模式

docker中,rootfs由内核挂载为“只读”模式,而后通过“联合挂载 ”技术额外挂载一个“可写”层;

位于下层的镜像称为父镜像(parent image),最底层的称为基础 镜像(base image)

最上层为“可读写”层,其下的均为“只读”层

QQ截图20180801140824

Registry  (docker镜像仓库)

在下载镜像时,如果不指定路径,默认是下载Docker Hub官方的镜像仓库里的镜像文件。

如果也没有指定tags(版本号);则默认下载latest(最新的)的版本。

Registry用于保存docker镜像,包括镜像的层次结构元数据

Repository  :由单个类型的docker镜像的所有迭代版本组成的镜像仓库 ;在镜像仓库之下。(例如:nginx;下面有多个版本的镜像文件,都是nginx的标签;但他都是nginx的镜像文件)

一个 Registry是由多个Repository镜像仓库所组成的。

https://quay.io/  (另一个镜像网站)

如果在此网上上下载格式为:docker pull quay.io/coreos/flannel:v0.10.0-arm64

(quay.io:官网地址:/coreos/flannel ;下图中所搜寻的flannel的前缀;:v0.10.0-arm64:版本号)

 

QQ截图20180801150316

 

QQ截图20180801150740

 镜像的制作 

#docker run –name b1 -it busybox:latest      #创建并启动一个容器
/ # mkdir -p /data/html
/ # cd /data/html
/data/html # vi index.html
     hello world!
不能将容器关闭或者退出,在容器运行状态下,另外开启一个linux的终端界面
# docker commit -p b1  #基于b1做新的镜像文件
sha256:7125d1bc1ed7fd23a0654432902386917ecf78d2deeda4d5933d05b61ed28597
# docker image ls  
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 7125d1bc1ed7 34 seconds ago 1.16MB  #由于并没有命名所以此镜像只有id号而没有名称
busybox latest e1ddd7948a1c 15 hours ago 1.16MB
nginx latest c82521676580 7 days ago 109MB
redis latest
#docker tag 2e8b205a2902 magedu/http:1.0     #由于刚创建的镜像没有名称和标签,使用不方便,可以创建名称和
标签:创建时要使用其id号来引用
#docker tag magedu/http:1.0 magedu/http:1.1    #给同一个镜像创建多个标签
# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
magedu/http 1.0 7125d1bc1ed7 2 minutes ago 1.16MB
magedu/http 1.1 7125d1bc1ed7 2 minutes ago 1.16MB
当一个镜像有多个标签时,删除一个标签不会将镜像删除,如果只有一个标签了,删除了最后一个标签就会将镜像删除了。
#docker image rm magedu/http:1.1     #删除其中一个镜像标签
#docker inspect nginx    #查看具体的镜像里的内容
#docker run –name ttt -it magedu/http:1.0    #开启新建的镜像

将镜像推送到官网

官网:https://hub.docker.com/

首先要在官网上注册一个个人的账号

登陆后创建一个仓库:Create Repository magedu/httpd   #仓库的名称

登陆:

#docker login -u yuanyaqiong    #如果是推送到官网上,不用写服务器的地址;如果不是则需要写服务器的地址

推送:

#docker push magedu/httpd   #如果不添加标签的化默认推送magedu/httpd;所有版本的

推送到阿里云的个人仓库

官网:https://cr.console.aliyun.com/cn-hangzhou/repositories  

注册账号,创建新的镜像仓库。

QQ截图20180801162411

 docker的四种网络模型

# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
da59a155e83a        bridge              bridge              local
01ece4a5d8e9        host                host                local
d2d9c9c358d6        none                null                local
null 无网卡的无网络模式,容器不需要和外界相连
bridge 桥接式 ,直接桥接到docker0网卡上。(默认使用的方法)
联盟式网络:让各个容器之间关于网络方面的名称空间是共用一个名称空间,然后再桥接到物理网卡上
docker容器都直接共用,物理网卡上。

默认创建的是bridge网桥的方式

# docker network inspect bridge   #查看网络信息
[
    {
        "Name": "bridge",  桥接
"Id": "da59a155e83a87790dc8cf209ea66ddb3873ec0a2d0c1dfbb6c41deb6e64efed",
        "Created": "2018-08-03T03:43:45.163050409+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1" 网关
                }
            ]
        },

docker bridge 网络

宿主机会自动创建docker0 网段,以后创建的每个容器都是docker0网段的IP地址,他们之间可以相互连接的。宿主机上的docker0就像一个虚拟的交换机,将各个容器相互连接起来。

Docker0为NAT桥,因此容器一般获得的是私有网络地址 。

# ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:4d:b8:81:c5  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

每创建一个docker容器运行就会生成一对网卡,一个在宿主机上,一个在容器上。

宿主机生成的网卡:(并将其关连到docker0的网卡上)

每个docker容器里生成的网卡及IP地址

# docker start -a -i b1  #b1容器的镜像是busybox:latest的打开方式
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:03  
          inet addr:172.17.0.3  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:8 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:648 (648.0 B)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

# docker exec -it web1 /bin/sh   #web1容器的镜像是nginx,run的情况下打开进入

每个docker容器里的网卡都可以ping通到宿主机的内网的IP地址,和外网的IP地址。

每创建一个docker容器就会生成一个iptables规则,将容器内的地址做转换,可以访问到外网。

/ # ping 192.168.130.7
PING 192.168.130.7 (192.168.130.7): 56 data bytes
64 bytes from 192.168.130.7: seq=0 ttl=64 time=0.216 ms
64 bytes from 192.168.130.7: seq=1 ttl=64 time=0.172 ms
64 bytes from 192.168.130.7: seq=2 ttl=64 time=0.150 ms

docker bridge网络下容器的几种网络模式

在同一个宿主机上的不同容器之间的访问:
如果有一个docker容器的nginx的服务,在另一个docker容器里应该是可以访问到nginx容器的nginx的web服务.
在宿主机上访问nginx容器的nginx的web服务。也是可以的。
另一台物理机要访问nginx容器的nginx的web服务器。无法直接访问,需要做地址关连,将nginx容器的IP地址关连到本地的内网或者外网的IP地址上去,这样外部的物理机就可以访问容器虚拟机的IP地址了。

创建网络名称空间,虚拟网卡,使其通信

#ip netns add r1  #创建网络名称空间r1
#ip netns add r2   #创建网络名称空间r2
#ip link add name veth1.1 type veth peer name veth1.2  #创建两个虚拟网卡
# ip link #查看虚拟网卡
11: veth1.2@veth1.1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
    link/ether b2:6d:48:6d:8e:2e brd ff:ff:ff:ff:ff:ff
12: veth1.1@veth1.2: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
    link/ether 16:1a:97:02:b6:a6 brd ff:ff:ff:ff:ff:ff
注意:默认虚拟网卡为被激活,使用ifconfig是不能查看到的
# ip link set dev veth1.2 netns r1  #把虚拟网卡移动到r1网络名称空间
# ip netns exec r1 ifconfig -a  #查看r1网络空间
veth1.2: flags=4098<BROADCAST,MULTICAST> mtu 1500
ether b2:6d:48:6d:8e:2e txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
# ip netns exec r1 ip link set dev veth1.2 name eth1 #把网络卡名为veth1.2改为网卡名为eth1
# ip netns exec r1 ifconfig -a
eth1: flags=4098<BROADCAST,MULTICAST> mtu 1500
ether b2:6d:48:6d:8e:2e txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
#ifconfig veth1.1 10.0.0.1/24 up #将宿主机里的虚拟网卡veth1.1创建一个地址并激活
#ifconfig
veth1.1: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 10.0.0.1 netmask 255.255.255.0 broadcast 10.0.0.255
ether 16:1a:97:02:b6:a6 txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
#ping 10.0.0.1 #宿主机来ping网络空间的虚拟IP地址
PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.049 ms

 创建各种网络模式的容器

# docker run --name f1 -it --rm busybox:latest  #创建一个busybox容器,退出后并删除
/ # exit
[root@centos7 ~]# docker run --name f1 -it --network none --rm busybox:latest  #创建一个null模式的busybox容器
/ # ifconfig
lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
# docker run --name f1 -it --network none -h centos7.magedu.com --rm busybox:latest  #创建容器时,指定容器的主机名centos7.magedu.com
/ #
# docker run --name f1 -it --network none -h centos7.magedu.com --dns 8.8.8.8 --rm busybox:latest  #创建容器时指定DNS服务器的地址
/ # cat /etc/resolv.conf 
search magedu.com
nameserver 8.8.8.8
#docker run –name f1 -it –network none -h t1.magedu –add-host www.magedu.com:192.168.7.7 –rm busybox:latest  #指定hosts文件的dns解析地址

创建一个使用共同虚拟网卡的两个容器

# docker run --name tt --rm -it magedu/http:1.0   #在宿主机上创建tt容器
/ # ifconfig  #查看容器tt的IP
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:04 
inet addr:172.17.0.4 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:8 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0 
RX bytes:648 (648.0 B) TX bytes:0 (0.0 B)

lo Link encap:Local Loopback 
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1 
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

/ # ping 127.0.0.1  #tt容器可以与宿主机的本地IP地址127.0.0.1连接
PING 127.0.0.1 (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: seq=0 ttl=64 time=0.056 ms
64 bytes from 127.0.0.1: seq=1 ttl=64 time=0.120 ms

# docker run --name tk --network container:tt --rm -it magedu/http:1.0  #在相同的宿主机上在创建一个tk容器和tt共用一个虚拟地址
/ # ifconfig  #查看容器tk的IP
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:04 
inet addr:172.17.0.4 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:38 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0 
RX bytes:5785 (5.6 KiB) TX bytes:0 (0.0 B)

lo Link encap:Local Loopback 
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1 
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

/ # ping 127.0.0.1   #tk容器可以与宿主机的本地IP地址127.0.0.1连接
PING 127.0.0.1 (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: seq=0 ttl=64 time=0.084 ms
64 bytes from 127.0.0.1: seq=1 ttl=64 time=0.140 ms
此时两个容器共享了一个虚拟IP地址

创建一个使用共同物理网卡的两个容器

# docker run --name tt --network host --rm -it magedu/http:1.0
/ # ifconfig
docker0 Link encap:Ethernet HWaddr 02:42:4D:B8:81:C5 
inet addr:172.17.0.1 Bcast:172.17.255.255 Mask:255.255.0.0
inet6 addr: fe80::42:4dff:feb8:81c5/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:33 errors:0 dropped:0 overruns:0 frame:0
TX packets:79 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0 
RX bytes:2548 (2.4 KiB) TX bytes:10149 (9.9 KiB)

ens33 Link encap:Ethernet HWaddr 00:0C:29:C8:4E:67 
inet addr:192.168.130.7 Bcast:192.168.130.255 Mask:255.255.255.0
inet6 addr: fe80::20c:29ff:fec8:4e67/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:7857 errors:0 dropped:0 overruns:0 frame:0
TX packets:4484 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000 
RX bytes:696429 (680.1 KiB) TX bytes:569044 (555.7 KiB)
# docker run --name tt1 --network host --rm -it magedu/http:1.0
/ # ifconfig
docker0 Link encap:Ethernet HWaddr 02:42:4D:B8:81:C5 
inet addr:172.17.0.1 Bcast:172.17.255.255 Mask:255.255.0.0
inet6 addr: fe80::42:4dff:feb8:81c5/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:33 errors:0 dropped:0 overruns:0 frame:0
TX packets:79 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0 
RX bytes:2548 (2.4 KiB) TX bytes:10149 (9.9 KiB)

ens33 Link encap:Ethernet HWaddr 00:0C:29:C8:4E:67 
inet addr:192.168.130.7 Bcast:192.168.130.255 Mask:255.255.255.0
inet6 addr: fe80::20c:29ff:fec8:4e67/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:7857 errors:0 dropped:0 overruns:0 frame:0
TX packets:4484 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000 
RX bytes:696429 (680.1 KiB) TX bytes:569044 (555.7 KiB)

以上两个容器直接关连到宿主机上的所有的物理网卡上了。此时在浏览器上就可以直接访问容器里的虚拟机了,因为容器里的虚拟机的IP地址和宿主机的IP地址是相同的。

/ # echo "hello" >/tmp/index.html  #在tt1容器里简单的配置虚拟机的http服务的主页面
/ # httpd -h /tmp/   #启动的时候指定主页面的路径

在浏览器上访问宿主机的IP,可以看到容器提供http服务页面

指定bridge的IP地址,不使用系统默认172.17.0.0/16的IP地址

#systemctl stop docker  #停止docker服务
#vim /etc/docker/daemon.json  #编辑添加加速器的配置文件
{
  "registry-mirrors": ["https://registry.docker-cn.com"],
 "bip": "10.0.0.1/16"
}
#systemctl start docker   #启动docker服务
#ifconfig  #查看IP
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 10.0.0.1 netmask 255.255.0.0 broadcast 10.0.255.255
inet6 fe80::42:4dff:feb8:81c5 prefixlen 64 scopeid 0x20<link>
ether 02:42:4d:b8:81:c5 txqueuelen 0 (Ethernet)
RX packets 33 bytes 2548 (2.4 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 79 bytes 10149 (9.9 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

 

# docker run --name dd1 -it --rm -v /data/bb2:/data busybox 
/ #

Docker Data Volume (存储卷)

Docker镜像由多个只读层叠加而成,启动容器时,Docker会加 载只读镜像层并在镜像栈顶部添加一个读写层

如果运行中的容器修改了现有的一个已经存在的文件,那该文件将会从读写层下面的只读层复制到读写层,该文件的只读版 本仍然存在,只是已经被读写层中该文件的副本所隐藏,此即 “写时复制(COW)”机制

“卷”是容器上的一个或多个“目录”,此类目录可绕过联合文件 系统,与宿主机上的某目录“绑定(关联)”

即使将容器删除,同步到宿主机上的数据也不会消失,保证数据的持久化。

Docker管理卷

Docker有两种类型的卷,每种类型都在容器中存在一个挂载点,但其在宿主机上的位置有所不同

1、Bind  mount  volume  (卷绑定到宿主机)

#docker run --name dd1 -it --rm -v /data/b2:data busybox  #创建一个容器,前面的路径为宿主机的路径,后面为容器的路径;两个位置的路径都不需要创建会自动生成的

/#

#docker inspect dd1  :用此命令可以查看容器的详细信息:(关连路径的详细信息)
 "Mounts": [
            {
                "Type": "bind",
                "Source": "/data/b2",
                "Destination": "/data",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],

此时在容器路径下/data/创建数据,会自动同步到指定的宿主机/data/b2/路径下的。

2、Docker-managed volume (docker管理卷)

只需要指定容器里的目录,docker引擎会自动关连到宿主机上对应的路径位置,可以通过探测容器的详细信息来查询。

#docker run –name dd1 -it -v /data busybox    #只指定容器的路径
#docker inspect dd1     #查看具体关连到本地的路径的信息
 "Mounts": [
            {
                "Type": "volume",
                "Name": "5d3a55d03a0f1e17650300265d17c795ee7edfc587cd3569edbae856ba62efc9",
                "Source": "/var/lib/docker/volumes/5d3a55d03a0f1e17650300265d17c795ee7edfc587cd3569edbae856ba62efc9/_data",  #宿主机上目录的具体路径
                "Destination": "/data",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],

此时在容器里/data/下创建数据,会自动同步到宿主机上的路径下的;有了脱离容器的持久状态。

两个docker容器共享一个卷

在同一个宿主机上
# docker run --name d1 -it --rm -v /data/b2:/data busybox
/ #
# docker run --name d2 -it --rm -v /data/b2:/app busybox
/ #
创建两个容器,指定相同的宿主机目录,容器的目录各不相同。此时,在宿主机/data/b2下创建一个文件,会同时同步到两个容器/data和/app目录下。

做一个基础的容器,在创建其他容器时,复制此文件的配置

# docker run --name base -it --rm -v /data/b2;/data busybox  #创建基础容器
/ # ifconfig  #查看网络
eth0      Link encap:Ethernet  HWaddr 02:42:0A:00:00:03  
          inet addr:10.0.0.3  Bcast:10.0.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:8 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:648 (648.0 B)  TX bytes:0 (0.0 B)/ # ls   #查看base容器的目录
bin   data  dev   etc   home  proc  root  sys   tmp   usr   var
/ # 
# docker run --name nginx --network container:base -it --rm --volumes-from base busybox   #创建新容器nginx,网络和卷的关连设置都是基于base容器的
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:0A:00:00:03  
          inet addr:10.0.0.3  Bcast:10.0.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:8 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:648 (648.0 B)  TX bytes:0 (0.0 B)/ # ls
bin   data  dev   etc   home  proc  root  sys   tmp   usr   var
/ # 
nginx容器的网络和卷设置和base容器的是一样的。

Dockerfil:制作镜像

大多从dockerhub上下载下来的容器镜像大多都不符合实际需求,许多配置参数都需要改动,比较麻烦,所以需要自己制作符合自己需求的容器镜像。

dockerfile的方式是讲应用的配置文件做成模板,每次运行一个镜像容器时,加载设定好的模板配置文件就可以实现对不同镜像的不同需求。

工作原理:在开启一个容器镜像时,不启动容器的主进程而是先开启另一个进程,读取模板配置文件里的参数,设定好容器主进程的个项环境变量参数,然后再打开容器的主进程。不通过去修改应用程序的配置文件,而是在启动程序时,给容器的应用传递环境变量(环境变量就存放在docker文件里)

FROM指令(指定制作镜像的基础镜像)

FROM指令是最重的一个且必须为Dockerfile文件开篇的第一个非注释行,用于为映射文件构建过程指定基准镜像,后续的指令运 行于此基准镜像所提供的运行环境。

实践中,基准镜像可以是任何可用镜像文件,默认情况下, docker build会在docker主机上查找指定的镜像文件,在其不存在 时,则会从Docker Hub Registry上拉取所需的镜像文件

如果找不到指定的镜像文件,docker build会返回一个错误信息

form 指定镜像的格式:

FROM <image>[:<tag>] :直接指定镜像名称
FROM <image>@<digest>   :指定镜像的哈希值;(防止在使用镜像时,被人在镜像里添加危害系统的代码)

LABEL(标签)

用于让镜像制作者提供本人的详细信息

LABEL:格式是键值数据对: LABEL maintainer= “magedu <mage@magedu.com>”

COPY指令

用于docker宿主机复制文件至创建的新映像文件

Syntax  格式

COPY <src> … <dest>
COPY [“<src>”,… “<dest>”]  列表格式:前面多个源文件,后面一个目标文件夹
<src>:要复制的源文件或目录,支持使用通配符
<dest>:目标路径,即正在创建的image的文件系统路径;建议为<dest>使用绝对路径,否则,COPY指定则以WORKDIR为其起始路径;

注意:在路径中有空白字符时,通常使用第二种格式用引号。

文件复制的规则:

<src>必须是build上下文中的路径,不能是其父目录中的文件

如果<src>是目录,则其内部文件或子目录会被递归复制,但<src>目录自身 不会被复制。不复制目录,只是将目录下的文件复制过去。

如果指定了多个<src>,或在<src>中使用了通配符,则<dest>必须是一个目录 ,且必须以/结尾

如果<dest>事先不存在,它将会被自动创建,这包括其父目录路径

例如:copy index.html /data/web/html/  (仅复制一个文件到要启动容器的目录下,容器的目录如果不存在,系统会默认创建的,index.html文件的路径在当前目录下及和dockerfile文件在同一目录下)

被直接下载 并保存为<dest>/<filename>

如果<src>是一个本地系统上的压缩格式的tar文件,它将被自动展开为一个目录 ,其行为类似于“tar -x”命令;然而通过URL网络上获取到的tar文件将不会自动 展开;

如果<src>有多个,或其间接或直接使用了通配符,则<dest>必须是一个以/结 尾的目录路径;如果<dest>不以/结尾,则其被视作一个普通文件,<src>的内 容将被直接写入到<dest>;

WORKDIR 指令   (指定容器的路径)

在使用copy和add命令时,用于指定容器的路径。

用于为Dockerfile中所有的RUN、CMD、ENTRYPOINT、COPY和 ADD指定设定工作目录

Syntax ɰ WORKDIR <dirpath> l 在Dockerfile文件中,WORKDIR指令可出现多次,其路径也可以为相对路径,不过 ,其是相对此前一个WORKDIR指令指定的路径 l 另外,WORKDIR也可调用由ENV指定定义的变量 ɰ 例如 l WORKDIR /var/log l WORKDIR $STATEPATH

例如:

WORKDIR /usr/local/src     (先指定好容器的路径)
ADD nginx-1.15.2.tar.gz ./   (引用时只写当前路径就可以了)

VOLUME指令 (卷的挂载)

用于在image中创建一个挂载点目录,以挂载Docker host上的卷或 其它容器上的卷

Syntax  格式

1
2
VOLUME <mountpoint>
VOLUME [“<mountpoint>”]

如果挂载点目录路径下此前在文件存在,docker run命令会在卷挂 载完成后将此前的所有文件复制到新挂载的卷中

例如:

VOLUME /data/mysql (前面路径为容器里的路径,后面宿主机的目录路径不指定会自动创建的,也可以自定义的指定)

这样就实现了将容器里的/data/mysql/  目录直接就挂载到了宿主机上了。

EXPOSE 指令  (暴露端口)

用于为容器打开指定要监听的端口以实现与外部通信;只能指定自己暴露的端口,不能指定自己的IP地址。需要动态绑定到宿主机上的所有地址和随机端口,因为本机到底是运行在哪个主机上不确定,且宿主机的哪个端口空闲也是不确定的,所以是随机指定的。

Syntax

EXPOSE <port>[/<protocol>] [<port>[/<protocol>] …]
<protocol>用于指定传输层协议,可为tcp或udp二者之一,默认为TCP协议
EXPOSE指令可一次指定多个端口,例如
EXPOSE 11211/udp 11211/tcp

只写在此文件里,是不会暴露的,只有在docker run 运行时添加-P选项就会读取此文件里的暴露的配置内容,为了防止安全才这样做。

ENV指令(定义容器的环境变量)

用于为镜像定义所需的环境变量,并可被Dockerfile文件中位于其 后的其它指令(如ENV、ADD、COPY等)所调用

调用格式为$variable_name或${variable_name}

dockerfile里的变量:
${variable:-word} 当变量有值时,使用原变量的值,如果没有给与变量赋值,则使用-号后面的值。
${variable:+word} 和上述变量相反,当变量有值时,使用+后面的值,变量没有值时,就没有值了

Syntax  格式

1
2
ENV <key> <value>
ENV <key>=<value> …

第一种格式中,<key>之后的所有内容均会被视作其<value>的组成部分 ,因此,一次只能设置一个变量;

第二种格式可用一次设置多个变量,每个变量为一个”<key>=<value>”的 键值对,如果<value>中包含空格,可以以反斜线(\)进行转义,也可通过 对<value>加引号进行标识;另外,反斜线也可用于续行

定义多个变量时,建议使用第二种方式,以便在同一层中完成所有功能

RUN指令

用于指定docker build过程中运行的程序,其可以是任何命令,但在基础镜像里需要有相对应的命令,否则也无法运行。

Syntax  格式

1
2
RUN <command>
RUN [“<executable>”, “<param1>”, “<param2>”]

第一种格式中,<command>通常是一个shell命令,且以“/bin/sh -c”来运行它, 这意味着此进程在容器中的PID不为1,不能接收Unix信号,因此,当使用 docker stop <container>命令停止容器时,此进程接收不到SIGTERM信号;

第二种语法格式中的参数是一个JSON格式的数组,其中<executable>为要运行的 命令,后面的<paramN>为传递给命令的选项或参数;然而,此种格式指定的命 令不会以“/bin/sh -c”来发起,因此常见的shell操作如变量替换以及通配符(?,* 等)替换将不会进行;不过,如果要运行的命令依赖于此shell特性的话,可以将 其替换为类似下面的格式。

RUN [“/bin/bash”, “-c”, “<executable>”, “<param1>”]

CMD指令  (定义镜像文件启动为容器时 将定义的程序运行为容器的主程序;如果此程序结束容器也会跟随者结束)

类似于RUN指令,CMD指令也可用于运行任何命令或应用程序, 不过,二者的运行时间点不同

RUN指令运行于映像文件构建过程中,而CMD指令运行于基于Dockerfile 构建出的新映像文件启动一个容器时

CMD指令的首要目的在于为启动的容器指定默认要运行的程序,且其运 行结束后,容器也将终止;不过,CMD指定的命令其可以被docker run的 命令行选项所覆盖

在Dockerfile中可以存在多个CMD指令,但仅最后一个会生效

Syntax
CMD <command>
CMD [“<executable>”, “<param1>”, “<param2>”]
CMD [“<param1>”,”<param2>”]

前两种语法格式的意义同RUN

第三种则用于为ENTRYPOINT指令提供默认参数

ENTRYPOINT指令

类似CMD指令的功能,用于为容器指定默认运行程序,从而使得 容器像是一个单独的可执行程序

与CMD不同的是,由ENTRYPOINT启动的程序不会被docker run命 令行指定的参数所覆盖,而且,这些命令行参数会被当作参数传 递给ENTRYPOINT指定指定的程序

不过,docker run命令的–entrypoint选项的参数可覆盖ENTRYPOINT指令,指定的程序Syntax 格式

例1:创建镜像(copy命令复制单个文件到容器目录下)

#mkdir imge1   #创建一个文件夹
#cd imge1/     #进入到此文件夹下
#vim Dockerfile  #创建一个dockerfie文件,注意创建的文件开头字母要大写
 #Description test image  #描述信息
  FROM busybox:latest      #基于什么镜像来制作
 MAINTAINER “magedu <mage@magedu.com>”   #指定镜像制作的人的信息
 #LABEL maintainer= “magedu <mage@magedu.com>”   #注释信息,新的指令用法
 copy index.html /data/web/html/    #需要在imge1目录下创建一个index.html文件
#vim index.html
 hello world! 
#cd ~
# docker build -t httpd:1.1 imge1/ #制作镜像 (httpd为自定义的仓库名;1.1为标签版本号;imge1/:为dockerfile文件的父目录。) Sending build context to Docker daemon 3.072kB Step 1/3 : FROM busybox:latest ---> e1ddd7948a1c Step 2/3 : MAINTAINER "magedu <mage@magedu.com>" ---> Running in 439d3cb17fc3 Removing intermediate container 439d3cb17fc3 ---> 8c513ec7b848 Step 3/3 : copy index.html /data/web/html/ ---> ec188d98a1a3 Successfully built ec188d98a1a3 Successfully tagged httpd:1.1 # docker image ls #查看本地镜像已生成新的文件 REPOSITORY TAG IMAGE ID CREATED SIZE httpd 1.1 ec188d98a1a3 23 seconds ago 1.16MB 基于上面制作的镜像文件来开启一个容器: #docker run –name hhh -it –rm httpd:1.1 #交互式的方式登陆进去查看dockerfile里复制到容器里的文件是否复制过去 / # cd /data/web/html/ /data/web/html # ls index.html

例2:创建镜像(copy命令复制目录下的多个文件到容器目录里)

#cd /root/imae1/
~/imge1]# cp -r /etc/yum.repos.d .  #复制/etc/yum.repos.d目录到 /root/imae1/目录下
~/imge1]# ls
Dockerfile  index.html  yum.repos.d
~/imge1]# vim Dockerfile 
#Description test image
FROM busybox:latest
MAINTAINER "magedu <mage@magedu.com>"
#LABEL maintainer= "magedu <mage@magedu.com>"
copy index.html /data/web/html/
copy yum.repos.d /etc/yum.repos.d/
其中yum.repos.d为目录。复制过去不复制目录,只复制目录下的文件,另外dockerfile文件里命令如果能写一行不要分两行来写,因为每一行都在运行容器时都是一层封装。
 ~/imge1]# docker build -t httpd:1.2 /root/imge1/
Sending build context to Docker daemon  20.48kB
Step 1/4 : FROM busybox:latest
 ---> e1ddd7948a1c
Step 2/4 : MAINTAINER "magedu <mage@magedu.com>"
 ---> Using cache
 ---> 8c513ec7b848
Step 3/4 : copy index.html /data/web/html/
 ---> Using cache
 ---> ec188d98a1a3
Step 4/4 : copy yum.repos.d /etc/yum.repos.d/
 ---> 5c6a8e8dbe66
Successfully built 5c6a8e8dbe66
Successfully tagged httpd:1.2
 ~/imge1]# docker run --name hhh -it --rm httpd:1.2
/ # cd /etc/yum.repos.d/   #以第二版本的镜像开启一个容器,查看是否将目录下的文件复制过去
/etc/yum.repos.d # ls
back       base.repo
/etc/yum.repos.d # ls
back       base.repo
/etc/yum.repos.d # cd /data/web/html/
/data/web/html # ls
index.html

例3:创建镜像(add命令下载网络上tar格式的文件和下载本地的tar格式的文件)

找一个网络上的tar格式的包,复制其url的路径http://nginx.org/download/nginx-1.12.2.tar.gz

#cd /root/imae1/
~/imge1]# vim Dockerfile 
#Description test image
FROM busybox:latest
MAINTAINER "magedu <mage@magedu.com>"
ADD http://nginx.org/download/nginx-1.12.2.tar.gz /usr/local/src/下载到容器上的路径
[root@centos7 ~/imge1]# cd
[root@centos7 ~]# docker build -t httpd:1.3 /root/imge1/ 
Sending build context to Docker daemon  20.48kB
Step 1/3 : FROM busybox:latest
 ---> e1ddd7948a1c
Step 2/3 : MAINTAINER "magedu <mage@magedu.com>"
 ---> Using cache
 ---> 8c513ec7b848
Step 3/3 : ADD http://nginx.org/download/nginx-1.12.2.tar.gz /usr/local/src/
Downloading  981.7kB/981.7kB
 ---> 8e9c27dcb249
Successfully built 8e9c27dcb249
Successfully tagged httpd:1.3
[root@centos7 ~]# docker run –name kkk -it –rm httpd:1.3 
docker: invalid reference format.
See 'docker run --help'.
[root@centos7 ~]# docker run --name kkk -it --rm httpd:1.3 
/ # cd /usr/local/src
/usr/local/src # ls
nginx-1.12.2.tar.gz #未解压缩

网络上的url路径下载的tar格式的包不会自动将其解压缩

但如果将tar格式的包下载到宿主机上的目录下,使用add命令,会将其自动的解压缩。

wget http://nginx.org/download/nginx-1.15.2.tar.gz  先将文件下载到本地/root/imge1/下

 #cd /root/imge1/
 ~/imge1]# wget http://nginx.org/download/nginx-1.15.2.tar.gz 
--2018-08-05 14:45:09--  http://nginx.org/download/nginx-1.15.2.tar.gz
Resolving nginx.org (nginx.org)... 206.251.255.63, 95.211.80.227, 2606:7100:1:69::3f, ...
Connecting to nginx.org (nginx.org)|206.251.255.63|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1025746 (1002K) [application/octet-stream]
Saving to: ‘nginx-1.15.2.tar.gz’

100%[======================================>] 1,025,746   20.9KB/s   in 64s    

2018-08-05 14:46:14 (15.7 KB/s) - ‘nginx-1.15.2.tar.gz’ saved [1025746/1025746]
~/imge1]# vim Dockerfile 
#Description test image
FROM busybox:latest
MAINTAINER "magedu <mage@magedu.com>"
ADD nginx-1.15.2.tar.gz /usr/local/src/
~/imge1]# docker build -t httpd:1.4 /root/imge1/ 
Sending build context to Docker daemon  1.047MB
Step 1/3 : FROM busybox:latest
 ---> e1ddd7948a1c
Step 2/3 : MAINTAINER "magedu <mage@magedu.com>"
 ---> Using cache
 ---> 8c513ec7b848
Step 3/3 : ADD nginx-1.15.2.tar.gz /usr/local/src/
 ---> 166b320352e0
Successfully built 166b320352e0
Successfully tagged httpd:1.4
 ~/imge1]# docker run --name kkk -it --rm httpd:1.4
/ # cd /usr/local/src/
/usr/local/src # ls
nginx-1.15.2  #解压缩

 

posted @ 2018-08-04 16:46  琼兔  阅读(548)  评论(0编辑  收藏  举报