Docker 基础管理

文章目录

  • 一、Docker 概述
    • 1. Docker 是什么
    • 2. Docker 的设计宗旨
    • 3. 容器的优点
    • 4. Docker 容器和虚拟机的区别
    • 5. namespace 的六项隔离
    • 6. Docker 核心的三个概念
      • 6.1 镜像
      • 6.2 容器
      • 6.3 仓库
  • 二、安装 Docker
  • 三、Docker 镜像与容器命令管理
    • 3.1 镜像命令管理
    • 3.2 容器命令管理
  • 四、Docker 网络
    • 4.1 Docker 网络实现原理
    • 4.2 Docker 网桥
    • 4.3 Docker 的网络模式
      • (1) 查看容器网络
      • (2) 创建网络
      • (3) 网络模式详解
        • ① host 模式
        • ② container 模式
        • ③ none 模式
        • ④ bridge 模式
    • 4.4 自定义网络
      • (1) 使用 bridge 指定 IP
      • (2) 创建自定义网络
  • 五、Docker 数据卷和数据卷容器
  • 六、容器互联
  • 七、端口映射
  • 八、Docker 镜像的创建
    • 8.1 基于现有镜像创建
    • 8.2 基于本地模板创建
    • 8.3 基于 dockerfile 创建


一、Docker 概述

1. Docker 是什么

  • Docker 是一个开源的应用容器引擎,基于 go 语言开发并遵循了 apache2.0 协议开源。
  • Docker 是在 Linux 容器里运行的开源工具,是一种轻量级的虚拟机。
  • Docker 的容器技术可以在一台主机上轻松为任何应用创建一个轻量级的、可移植的、自给自足的容器。
  • 目前 Docker 只能支持 64 位系统。

2. Docker 的设计宗旨

Docker 基础管理_第1张图片

  • Docker 的 Logo 设计为蓝色鲸鱼,拖着许多集装箱。鲸鱼可看作为宿主机,集装箱可理解为相互隔离的容器,每个集装箱中都包含自己的应用程序。

  • Docker 的设计宗旨:Build,Ship and Run Any APP,Anywhere
    即通过对应用组件的封装、发布、部署、运行等生命周期的管理,达到应用组件级别的一次封装,导出运行的目的。这里的组件,既可以是一个应用,也可以是一套服务,甚至是一个完整的操作系统。

3. 容器的优点

容器化越来越受欢迎,因为容器有如下特点:

  • 灵活:即使是最复杂的应用也可以集装箱化
  • 轻量级:容器利用并共享主机内核
  • 可互换:可以即时部署更新和升级
  • 便携式:可以再本地构建,部署到云,并在任何地方运行
  • 可扩展:可以增加并自动分发容器副本
  • 可堆叠:可以垂直和即时堆叠服务

4. Docker 容器和虚拟机的区别

  • 容器是在 Linux 上本机运行,并与其他容器共享主机的内核,它运行的是一个独立的进程,不占用其他任何可执行文件的内存,非常轻量。
  • 虚拟机运行的是一个完整的操作系统,通过虚拟机管理程序对主机资源进行虚拟访问,相比之下需要的资源更多。
特性 Docker 容器 openstack 虚拟机
部署难度 非常简单 组件多,部署复杂
启动速度 秒级 分钟级
执行性能 和物理系统几乎一致 vm 会占用一些资源
镜像体积 镜像 MB 级别 虚拟机镜像 GB 级别
管理效率 管理简单 组件相互依赖,管理复杂
可管理性 单进程 完整的系统管理
网络连接 比较弱 借助 neutron 可以灵活组件各类网络管理
性能 接近原生(直接在内核中运行) 50% 左右损失
系统支持量(单机) 上千个 几十个
隔离性 进程级别 操作系统级别
封装程度 只打包项目代码和依赖关系,共享宿主机内核 完整的操作系统,与宿主机隔离

5. namespace 的六项隔离

docker 本质就是宿主机的一个进程,docker 是通过 namespace 实现资源隔离,通过 cgroup 实现资源限制,通过写时复制技术 copy-on-write 实现了高效的文件操作(类似虚拟机的磁盘比如分配 500G 并不是实际占用物理磁盘 500G)。

namespace 系统调用参数 隔离内容
UTS CLONE_NEWUTS 主机名与域名
IPC CLONE_NEWWIPC 信号量、消息队列和共享内存
PID CLONE_NEWPID 进程编号
NETWORK CLONE_NEWNET 网络设备、网络栈、端口等
MOUNT CLONE_NEWNS 挂载点(文件系统)
USER CLONE_NEWUSER 用户和用户组(3.8 以后的内核才支持)

6. Docker 核心的三个概念

Docker 基础管理_第2张图片

6.1 镜像

  • Docker 的镜像是创建容器的基础,类似虚拟机的快照,可以理解为一个面向 Docker 容器引擎的只读模板。
  • 通过镜像启动一个容器,一个镜像是一个可执行的包,其中包括运行应用程序所需要的所有内容包含代码,运行时间、库、环境变量和配置文件。
  • Docker 镜像也是一个压缩包,只是这个压缩包不只是可执行文件,环境部署脚本,它还包含了完整的操作系统。因为大部分的镜像都是基于某个操作系统来构建,所以很轻松的就可以构建本地和远程一样的环境,这也是 Docker 镜像的精髓。

6.2 容器

  • Docker 的容器是从镜像创建的运行实例,它可以被启动、停止和删除。所创建的每一个容器都是相互隔离、互不可见,以保证平台的安全性。
  • 可以把容器看做是一个简易版的 Linux 环境(包括 root 用户权限、镜像空间、用户空间和网络空间等)和运行在其他的应用程序。

6.3 仓库

  • Docker 仓库是用来集中保存镜像的地方,当创建了自己的镜像之后,可以使用 push 命令将它上传到公有仓库或者私有仓库。当下次要在另外一台机器上使用这个镜像时,只需从仓库获取。
  • Docker 的镜像、容器、日志等内容全部都默认存储在 /var/lib/docker 目录下。

二、安装 Docker

#环境配置
systemctl stop firewalld && systemctl disable firewalld
setenforce 0

#安装依赖包
yum -y install yum-utils device-mapper-persistemt-data lvm2

#设置阿里云镜像源
cd /etc/yum.repos.d/
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

#安装 docker-ce 社区版(企业版叫 docker-ee,收费)
yum -y install docker-ce

#启动
systemctl enable docker && systemctl start docker

配置阿里云镜像加速

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://4iv7219l.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

网络优化

cat >> /etc/sysctl.conf <<EOF
net.ipv4.ip_forward=1
EOF

sysctl -p
systemctl restart network
systemctl restart docker

一键安装

[root@c7-1 ~]#cat docker.sh 
#!/bin/bash

#环境配置
systemctl stop firewalld && systemctl disable firewalld
setenforce 0

#安装依赖包
yum -y install yum-utils device-mapper-persistemt-data lvm2

#设置阿里云镜像源
cd /etc/yum.repos.d/
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

#安装 docker-ce 社区版(企业版叫 docker-ee,收费)
yum -y install docker-ce

#配置阿里云镜像加速(尽量使用自己的)
#地址 https://help.aliyun.com/document_detail/60750.html
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://4iv7219l.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload

#网络优化
cat >> /etc/sysctl.conf <<EOF
net.ipv4.ip_forward=1
EOF

sysctl -p
systemctl restart network
systemctl enable docker && systemctl restart docker

PS
docker-server 端配置文件 daemon.json

#生产配置示例,在 daemon.json 中定义
{
     
        "graph": "/data/docker",
        "storage-driver": "overlay2",
        "insecure-registries": ["registry.access.redhat.com","quary.io"]
        "registry-mirrors": ["https://q"]
        "bip": "172.7.5.1/24",
        "exec-opts": ["native.cgroupdriver=systemd"],
        "live-restore": true
}

#参数说明
"graph": "/data/docker",		#指定数据目录
"storage-driver": "overlay2",	#指定存储引擎
"insecure-registries": ["registry.access.redhat.com","quary.io"]	#私有仓库
"registry-mirrors": ["https://q"]	#配置镜像加速
"bip": "172.7.5.1/24",				#docker 网络,中间两位建议和宿主机一样,容器有问题好定位在哪个宿主机	
"exec-opts": ["native.cgroupdriver=systemd"],	#启动时候的额外参数(驱动,k8s使用)
"live-restore": true			#当docker容器引擎挂掉的时候,使用docker跑起来的容器还能运行(分离)

三、Docker 镜像与容器命令管理

3.1 镜像命令管理

Docker 基础管理_第3张图片

PS:

  • docker client 客户端连接到了服务端(服务端是以一个守护进程的形式跑在操作系统里面的)restful api 典型的 C/S 架构
  • 由 docker 服务端的守护进程从 docker hub 上下载了镜像(PS:服务端会先检查本地系统是否有这个镜像)
  • 服务端创建了一个新的容器,然后从拉去的这个镜像启动了一个容器,容器执行了脚本/可执行程序让我们可以查看/使用
  • docker 服务端把这些信息流(传递)返回到客户端并展示出来(展示在终端上)
#查询 docker 版本和信息
docker version
docker info

#搜索镜像(可以自己制作镜像上传本地或官网仓库 dockerfile)
docker search <镜像名>
 
#下载镜像
docker pull <镜像名>

#查看镜像列表
docker images

#查看镜像详细信息
docker inspect <镜像 ID>

#给镜像打标签
docker tag <镜像名>:<原标签> <镜像名>:<新标签>
#docker tag nginx:latest nginx:lnmp

#删除镜像
docker rmi <镜像名>
docker rmi <镜像标签>
docker rmi <镜像 ID>
docker rmi `docker images -aq`		#删除所有镜像
docker images | awk 'NR>=2{print "docker rmi -f "$3}' | bash

#镜像导出
docker save -o <导出的文件名> <镜像名>
#docker save -o nginx_v1 nginx:latest

#镜像导入
docker load < [镜像文件]
#docker load < nginx_v1

3.2 容器命令管理

Docker 基础管理_第4张图片
Docker 基础管理_第5张图片

#查询容器
docker ps -a

#查看容器占用系统资源信息
docker stats

#创建容器
docker create -it nginx:latest /bin/bash
#常用参数说明
> -i 让容器的标准输入保持打开
> -t 分配一个伪终端
> -d 以后台守护进程的方式运行

#开启/停止/重启 容器
docker start <容器 ID>
docker stop <容器 ID>
docker restart <容器 ID>

#后台运行,指定容器名称为 test
docker run -itd --name test nginx:latest /bin/bash

#进入容器
docker exec -it <容器 ID> /bin/bash		#exit 退出

#容器 导出/导入
docker export [容器 ID] > [文件名]
docker import [容器文件名] [指定镜像名称]		#导入的是镜像

#批量停止容器
docker ps -a | awk 'NR>=2{print "docker stop "$1}' | bash
docker ps -a | awk 'NR>=2{print $1}' | xargs docker stop

#批量删除容器
docker rm -f `docker ps -aq`
docker ps -a | awk 'NR>=2{print "docker rm "$1}' | bash
docker ps -a | awk 'NR>=2{print $1}' | xargs docker rm -f

#批量删除 "exit" 状态(指定状态)的容器
for i in `docker ps -a | grep -i exit | awk '{print $1}'`; do docker rm -f $i;done

#查看容器进程号
docker inspect -f '{
     {.State.Pid}}' <容器名>
docker inspect -f '{
     {.State.Pid}}' <容器 ID>

容器与宿主机之间文件的复制

docker run -itd --name nginx_test nginx:latest /bin/bash

#主机复制到容器
[root@tengxun-02 ~]#touch testfile
[root@tengxun-02 ~]#ls
testfile
[root@tengxun-02 ~]#docker cp testfile nginx_test:/opt
[root@tengxun-02 ~]#docker exec -it nginx_test bash
root@2ca07b152329:/# cd /opt
root@2ca07b152329:/opt# ls
testfile

#容器复制到主机
root@2ca07b152329:/opt# ls
testfile
root@2ca07b152329:/opt# touch haha
root@2ca07b152329:/opt# ls
haha  testfile
root@2ca07b152329:/opt# exit  
exit
[root@tengxun-02 ~]#docker cp nginx_test:/opt/haha .
[root@tengxun-02 ~]#ls
haha  testfile

进入容器没有 systemctl 命令解决

添加 --privileged=true(指定此容器是否为特权容器),使用此参数,则不能用 attach。
> 示例:
docker run -itd --name test3 --privileged=true centos /sbin/init

`/sbin/init 内核启动时主动呼叫的第一个进程`

可以使用 docker inspect <容器ID>
docker ps -a
docker exec -it <容器ID> /bin/bash
yum install httpd -y
systemctl status httpd

docker 在后台的标准运行过程:
(1)检查本地是否存在指定的镜像。当镜像不存在时,会从公有仓库下载;
(2)利用镜像创建并启动一个容器;
(3)分配一个文件系统给容器,在只读的镜像层外面挂载一层可读写层;
(4)从宿主主机配置的网桥接口中桥接一个虚拟机接口到容器中;
(5)分配一个地址池中的IP地址给容器;
(6)执行用户指定的应用程序,执行完毕后容器被终止运行。

四、Docker 网络

4.1 Docker 网络实现原理

  Docker 使用 Linux 桥接,在宿主机虚拟一个 Docker 容器网桥(docker0),Docker 启动一个容器时会根据 Docker 网络的网段分配给容器一个 IP 地址,称为 Container-IP,同时 Docker 网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的 Container-IP 直接通信。

  • docker0:容器的网关,绑定物理网卡,负责做 NAT 地址转换、端口映射
  • docker0 本身也是一种容器
[root@huawei-01 ~]#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:2e:57:4a:09  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

..........

[root@huawei-01 ~]#docker run -itd --name nginx_01 nginx:latest /bin/bash
7fc40ddb606d02a42ef613bd5357fb1c1ff3f2cd75d693b07ec2b763a227a3ee
[root@huawei-01 ~]#docker ps -a
CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS         PORTS     NAMES
7fc40ddb606d   nginx:latest   "/docker-entrypoint.…"   4 seconds ago   Up 3 seconds   80/tcp    nginx_01
[root@huawei-01 ~]#docker inspect 7fc40ddb606d
..........
            "Networks": {
     
                "bridge": {
     
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "3b3ea8498805a90c4c69dcc48e37253aada9c91222023ad7e3ca5584efd1c659",
                    "EndpointID": "bfa5118a2999e5ae6bb2e9fb30303627a1b163470416c810ef22cfc073638d1f",
                    "Gateway": "172.17.0.1",	#docker0 的 IP 作为容器网关
                    "IPAddress": "172.17.0.2",	#容器 IP 实现容器内部通信
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
                }
            }
        }
    }
]

4.2 Docker 网桥

  Docker 网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着外部网络无法直接通过 Container-IP 访问到容器。如果希望容器能够被外部网络访问到,可以通过 映射容器端口到宿主主机(端口映射),即 docker run 创建容器时通过 -p | -P 参数来启用,访问容器的时候就通过 [宿主机 IP]:[容器端口] 访问容器。

PS:

  • -P 将容器内部开放的网络端口随机映射到宿主机的一个端口上;
  • -p 指定要映射的端口,一个指定端口上只可以绑定一个容器。支持的格式如下:
    IP:HOSTPORT:CONTAINERPORT:指定 ip、指定宿主机 port、指定容器 port
    适用于映射到指定地址的指定端口
    eg:将容器的 5000 端口映射到指定地址 127.0.0.1 的 5000 端口上
    docker run -itd -p 127.0.0.1:5000:5000 docker.io/centos:latest /bin/bash
[root@tengxun-02 ~]#docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@tengxun-02 ~]#docker run -itd --name nginx_01 -p 8080:80 nginx:latest /bin/bash
540cc92956a8bc393da393d3a53c78ee7fd314ea2049994be04e994af59d7f8a
[root@tengxun-02 ~]#docker ps -a
CONTAINER ID   IMAGE          COMMAND       CREATED          STATUS          PORTS                  NAMES
540cc92956a8   nginx:latest   "/bin/bash"   12 seconds ago   Up 12 seconds   0.0.0.0:8080->80/tcp   nginx_01
[root@tengxun-02 ~]#docker exec -it 540cc92956a8 /bin/bash -c nginx
2021/11/26 08:07:00 [notice] 7#7: using the "epoll" event method
2021/11/26 08:07:00 [notice] 7#7: nginx/1.21.4
2021/11/26 08:07:00 [notice] 7#7: built by gcc 10.2.1 20210110 (Debian 10.2.1-6) 
2021/11/26 08:07:00 [notice] 7#7: OS: Linux 3.10.0-1160.11.1.el7.x86_64
2021/11/26 08:07:00 [notice] 7#7: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2021/11/26 08:07:00 [notice] 13#13: start worker processes
2021/11/26 08:07:00 [notice] 13#13: start worker process 14
2021/11/26 08:07:00 [notice] 13#13: start worker process 15
[root@tengxun-02 ~]#netstat -antp |grep 8080
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      5877/docker-proxy   
[root@tengxun-02 ~]#netstat -antp |grep 80
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      5877/docker-proxy   
tcp        0      0 10.0.24.9:22            180.111.206.87:24590    ESTABLISHED 476/sshd: root@pts/ 
tcp        0     52 10.0.24.9:22            180.111.206.87:23724    ESTABLISHED 25140/sshd: root@pt 
tcp        0      0 10.0.24.9:54800         169.254.0.138:8086      ESTABLISHED 16932/tat_agent    

测试访问(云主机需在防火墙配置规则)

[root@tengxun-02 ~]#curl 49.232.8.65:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html {
      color-scheme: light dark; }
body {
      width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

注意:
IP:HOSTPORT:CONTAINERPORT
指定 ip、指定宿主机 port、指定容器 port
0.0.0.0:8080->80/tcp
外网是无法访问容器内的 80 端口的,将容器的 80 端口映射到宿主机的 8080 端口上,外网就可以通过宿主机的 8080 端口访问容器内的应用服务。

docker 端口映射

4.3 Docker 的网络模式

网络模式 说明
Host 容器将不会虚拟出自己的网卡,配置自己的 IP 等,而是使用宿主机的 IP 和端口。
Container 创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围。
None 该模式关闭了容器的网络功能。
Bridge 默认为该模式,此模式会为每一个容器分配、设置 IP 等,并将容器连接到一个 Docker0 虚拟网桥,通过 docker0 网桥以及 iptables nat 表配置与宿主机通信。
自定义网络 自定义网络后,可指定容器 IP

(1) 查看容器网络

安装 Docker 时,它会自动创建三个网络:bridge(创建容器默认连接到此网络)、none、host。

[root@tengxun-02 ~]#docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
d1c5e817b704   bridge    bridge    local
79d2533e9fb2   host      host      local
c209ac067e43   none      null      local
[root@tengxun-02 ~]#docker network list
NETWORK ID     NAME      DRIVER    SCOPE
d1c5e817b704   bridge    bridge    local
79d2533e9fb2   host      host      local
c209ac067e43   none      null      local

(2) 创建网络

  Docker 内置(bridge、host、none)三个网络,运行容器时可以使用 --net | --network 标志来指定容器应连接到哪些网络。如不指定,docker 守护程序默认将容器连接到 bridge 网络。

- host 模式:使用 --net=host 指定
- none 模式:使用 --net=none 指定
- container 模式:使用 --net=container:NAME_or_ID 指定
- bridge 模式:使用 --net=bridge 指定(默认设置,可省略)

(3) 网络模式详解

① host 模式

Docker 基础管理_第6张图片
  相当于 Vmware 中的桥接模式,与宿主机在同一个网络中,但没有独立 IP 地址。Docker 使用了 Linux 的 Namespaces 技术来进行资源隔离,如 PID Namespace 隔离进程,Mount Namespace 隔离文件系统,Network Namespace 隔离网络等。
  一个 Network Namespace 提供了一份独立的网络环境,包括网卡、路由、iptable 规则等都与其他的 Network Namespace 隔离。一个 Docker 容器一般会分配一个独立的 Network Namespace。但如果启动容器的时候使用 host 模式,那么这个容器将不会获得一个独立的 Network Namespace,而是和宿主机共用一个 Network Namespace。容器将不会虚拟出自己的网卡、配置自己的 IP 等,而是使用宿主机的 IP 和端口。

[root@huawei-01 ~]#docker run -itd --name nginx_01 --net=host nginx:latest bash
9d9892111b13dc8dd352b04997202fbef575fbee32694047783d363c34a2997f
[root@huawei-01 ~]#docker ps -a
CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS         PORTS     NAMES
9d9892111b13   nginx:latest   "/docker-entrypoint.…"   4 seconds ago   Up 3 seconds             nginx_01
[root@huawei-01 ~]#docker inspect -f '{
     {.State.Pid}}' nginx_01		#查看容器进程
3448
[root@huawei-01 ~]#ll /proc/3448/ns		#查看容器的进程、网络、文件系统等命名空间编号
total 0
lrwxrwxrwx 1 root root 0 Nov 26 16:58 cgroup -> cgroup:[4026531835]
lrwxrwxrwx 1 root root 0 Nov 26 16:58 ipc -> ipc:[4026532523]
lrwxrwxrwx 1 root root 0 Nov 26 16:58 mnt -> mnt:[4026532521]
lrwxrwxrwx 1 root root 0 Nov 26 16:58 net -> net:[4026531888]
lrwxrwxrwx 1 root root 0 Nov 26 16:58 pid -> pid:[4026532524]
lrwxrwxrwx 1 root root 0 Nov 26 16:58 pid_for_children -> pid:[4026532524]
lrwxrwxrwx 1 root root 0 Nov 26 16:58 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Nov 26 16:58 uts -> uts:[4026532522]
[root@huawei-01 ~]#docker run -itd --name nginx_02 --net=host nginx:latest bash
0550d4df0634f6c4c859b56818f26dd9c0b2d6470543d3414085744de050812b
[root@huawei-01 ~]#docker inspect -f '{
     {.State.Pid}}' nginx_02
3526
[root@huawei-01 ~]#ll /proc/3526/ns
total 0
lrwxrwxrwx 1 root root 0 Nov 26 17:01 cgroup -> cgroup:[4026531835]
lrwxrwxrwx 1 root root 0 Nov 26 17:01 ipc -> ipc:[4026532527]
lrwxrwxrwx 1 root root 0 Nov 26 17:01 mnt -> mnt:[4026532525]
lrwxrwxrwx 1 root root 0 Nov 26 17:01 net -> net:[4026531888]
lrwxrwxrwx 1 root root 0 Nov 26 17:01 pid -> pid:[4026532528]
lrwxrwxrwx 1 root root 0 Nov 26 17:01 pid_for_children -> pid:[4026532528]
lrwxrwxrwx 1 root root 0 Nov 26 17:01 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Nov 26 17:01 uts -> uts:[4026532526]
# net 与 user 的命名空间相同,host 模式与系统共享 IP

② container 模式

Docker 基础管理_第7张图片
  这个模式指定新容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。

[root@docker ~]# docker run -itd --name test1 centos:7 bash
16cfef748ce1e1653e19925b6c38b28f70ebadb85a4ff5c8913befe1d1b6a7e9
[root@docker ~]# docker inspect -f '{
     {.State.Pid}}' test1
5428
[root@docker ~]# ls -l /proc/5428/ns
总用量 0
lrwxrwxrwx 1 root root 0 1011 16:18 ipc -> ipc:[4026532578]
lrwxrwxrwx 1 root root 0 1011 16:18 mnt -> mnt:[4026532576]
lrwxrwxrwx 1 root root 0 1011 16:13 net -> net:[4026532581]
lrwxrwxrwx 1 root root 0 1011 16:18 pid -> pid:[4026532579]
lrwxrwxrwx 1 root root 0 1011 16:18 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 1011 16:18 uts -> uts:[4026532577]
[root@docker ~]# docker run -itd --name test2 --net=container:test1 centos:7 bash
477032acba96fa0f4adb590a6846792fa99615e2eb9744e250cf14a9d7092a53
[root@docker ~]# docker inspect -f '{
     {.State.Pid}}' test2
5597
[root@docker ~]# ls -l /proc/5597/ns
总用量 0
lrwxrwxrwx 1 root root 0 1011 16:20 ipc -> ipc:[4026532699]
lrwxrwxrwx 1 root root 0 1011 16:20 mnt -> mnt:[4026532697]
lrwxrwxrwx 1 root root 0 1011 16:20 net -> net:[4026532581]
lrwxrwxrwx 1 root root 0 1011 16:20 pid -> pid:[4026532700]
lrwxrwxrwx 1 root root 0 1011 16:20 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 1011 16:20 uts -> uts:[4026532698]
# net 与 user 的命名空间相同,container 模式之间共享 IP

③ none 模式

Docker 基础管理_第8张图片
  使用 none 模式,Docker 容器拥有自己的 Network Namespace,但是并不为 Docker 容器进行任何网络配置。也就是说,这个 Docker 容器没有网卡、IP、路由等信息。这种网络模式下容器只有 lo 回环网络,没有其他网卡。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。

④ bridge 模式

Docker 基础管理_第9张图片
  bridge 模式是 docker 的默认网络模式,不用 --net 参数默认 bridge 模式。
相当于 Vmware 中的 nat 模式,容器使用独立 Network Namespace,并连接到 docker0 虚拟网卡。通过 docker0 网桥以及 iptables nat 表配置与宿主机通信,此模式会为每一个容器分配 Network Namespace、设置 IP 等,并将一个主机上的 Docker 容器连接到一个虚拟网桥上。

  • 当 docker 进程启动时,会在主机上创建一个名为 Docker0 的虚拟网桥,此主机上启动的 Docker 容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。
  • 从 docker0 子网中分配一个 IP 给容器使用,并设置 docker0 的 IP 地址为容器的默认网关。在主机上创建一对虚拟网卡 veth pair 设备。veth 设备总是成对出现的,它们组成了一个数据的通道,数据从一个设备进入,就会从另一个设备出来。因此,veth 设备常用来连接两个网络设备。
  • Docker 将 veth pair 设备的一端放在新创建的容器中,并命名为 eth0(容器的网卡),另一端放在主机中,以 veth* 这样类似的名字命名,并将这个网络设备加入到 docker0 网桥中。可以通过 brctl show 命令查看。
  • 使用 docker run -p 时,docker 实际是在 iptables 做了 DNAT 规则,实现端口转发功能。可以使用 iptables -t nat -vnL 查看。
[root@docker ~]# docker run -itd --name test1 -P centos:7 bash
92f615aecf1e9e22956446536db4bcfa91d2ce94dd9e3e9253c40a5e1d2b0fde
[root@docker ~]# docker ps -a
CONTAINER ID   IMAGE      COMMAND   CREATED          STATUS          PORTS     NAMES
92f615aecf1e   centos:7   "bash"    15 seconds ago   Up 14 seconds             test1
[root@docker ~]# iptables -t nat -vnL
······
Chain POSTROUTING (policy ACCEPT 531 packets, 39905 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 MASQUERADE  all  --  *      !docker0  172.17.0.0/16        0.0.0.0/0           
······

4.4 自定义网络

(1) 使用 bridge 指定 IP

直接使用 bridge 模式是无法支持指定 IP 运行 docker 的,例如执行以下命令就会报错:

[root@docker ~]# docker run -itd --name test1 --network=bridge --ip 172.17.0.8 centos:7 bash
0e1c5c2a0ed99d3e857dbf9a42046c670235d4eac4a5aa2690e4d7ce703cca5e
docker: Error response from daemon: user specified IP address is supported on user defined networks only.
# IP 错误,无法使用
[root@docker ~]# docker ps -a
CONTAINER ID   IMAGE      COMMAND   CREATED              STATUS    PORTS     NAMES
0e1c5c2a0ed9   centos:7   "bash"    About a minute ago   Created             test1
[root@docker ~]# docker start test1
Error response from daemon: user specified IP address is supported on user defined networks only
Error: failed to start containers: test1
# IP 错误,无法启动

(2) 创建自定义网络

可以先自定义网络,再使用指定 IP 运行 docker 容器

[root@c7-1 ~]#docker network create --subnet=172.111.0.0/16 --opt "com.docker.network.bridge.name"="docker" mynetwork
3452df02a82449b29199394483d6c99a4c9c3406c3ffdbf588240de6a508e9d6
[root@c7-1 ~]#ifconfig
docker: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.111.0.1  netmask 255.255.0.0  broadcast 172.111.255.255
        ether 02:42:a7:15:d0:34  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

······
[root@c7-1 ~]#docker network ls
NETWORK ID     NAME        DRIVER    SCOPE
a4f6af884c35   bridge      bridge    local
9397ae985a66   host        host      local
3452df02a824   mynetwork   bridge    local
3d49189a111f   none        null      local

[root@c7-1 ~]#docker run -itd --name centos-01 --net mynetwork --ip 172.111.0.11 centos:7 bash
d45b5b5a400245c8f280796c5286eeced9b7959bdfa2fb0a9d50d38b5c89224b
[root@c7-1 ~]#docker ps -a
CONTAINER ID   IMAGE         COMMAND    CREATED          STATUS                  PORTS     NAMES
d45b5b5a4002   centos:7      "bash"     13 seconds ago   Up 12 seconds                     centos-01
5c6260be004b   hello-world   "/hello"   2 days ago       Exited (0) 2 days ago             goofy_haslett
[root@c7-1 ~]#docker exec -it centos-01 bash
[root@d45b5b5a4002 /]# ifconfig
bash: ifconfig: command not found
[root@d45b5b5a4002 /]# yum -y install net-tools
[root@d45b5b5a4002 /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.111.0.11  netmask 255.255.0.0  broadcast 172.111.255.255
        ether 02:42:ac:6f:00:0b  txqueuelen 0  (Ethernet)
        RX packets 5846  bytes 19765435 (18.8 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 3947  bytes 216686 (211.6 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 69  bytes 6309 (6.1 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 69  bytes 6309 (6.1 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

总结

#查看网络列表
docker network ls

#查看容器信息(包含配置、环境、网关、挂载、cmd 等信息)
docker inspect <容器 ID>

#指定分配容器 IP 地址
docker run -itd --name test1 --network bridge --ip 172.17.0.10 centos:latest /bin/bash
#以上会报错

#自定义网络固定 IP
docker network create --subnet=172.18.0.0/16 mynetwork
docker run -itd --name test2 --net mynetwork --ip 172.18.0.100 centos:latest /bin/bash

#暴露端口
> -p 自定义端口(宿主机端口:容器内端口)
> -P 随机瑞口( -P 随机端口范围 49153-65535)
docker run -itd -p 333:80 nginx /bin/bash (docker 0)
docker run -itd -P nginx /bin/bash

#在宿主机环境执行容器内命令
docker exec -it <容器ID> /bin/bash -c 'nginx'	#启动 nginx
docker exec <容器ID/容器name> 执行的命令

五、Docker 数据卷和数据卷容器

  • 管理 Docker 容器中数据主要有两种方式:数据卷(Data Volumes)和数据卷容器(Data Volumes Containers)。

  • 数据卷是一个供容器使用的特殊目录,位于容器中。可将宿主机的目录挂载到数据卷上,对数据卷的修改操作立刻可见,并且更新数据不会影响镜像,从而实现数据在宿主机与容器之间的迁移。数据卷的使用类似于 Linux 下对目录进行的 mount 操作。

  • 如果需要在容器之间共享一些数据,最简单的方法就是使用数据卷容器。数据卷容器是一个普通的容器,专门提供数据卷给其他容器挂载使用。

数据卷(容器和宿主机共享文件)

docker pull centos

#宿主机目录 /var/www 挂载容器中的 /data1
docker run -v /var/www:/data1 --name web1 -it centos /bin/bash

[roote202dd484fd62 / ]#cd /data1/
[root@202dd484fd62 data1]# touch test123
#返回宿主机进行查看
[root@localhost ~]#ls /var/www/

#应用场景
原理:将容器内部的配置文件目录,挂载到宿主机指定目录下。
作用:
① 修改配置文件例如:nginx.conf /usr/local/nginx/conf/nginx.conf ---> /container_nginx/conf/nginx.conf
② 容器内部产生的日志,如何收集将容器内部存放日志文件的目录挂载到宿主机指定目录下 /container_nginx/log/access_log/access_log
③ 传入变量挂载到宿主机在宿主机上添加变量内容,将变量放入共享目录,在容器中 /etc/profile 直接加载就可以
export xxdir=/data/data1/xx-

数据卷容器(容器之间共享文件)

#数据卷容器
docker run --name web100 -v /data1 -v /data2 -itd centos /bin/bash

#新容器挂载数据卷容器 web100
docker run -itd --volumes-from web100 --name db1 centos /bin/bash

> 原理:让两个容器实现数据共享
php --> mysql 之间想要通讯借助于 socket 通讯文件

示例:

#创建容器并创建两个目录
[root@tengxun-02 ~]#docker run --name web100 -v /data1 -v /data2 -itd centos:7 /bin/bash
0f182c3e3a35bed01f3063a765ba553fafb4995d823709f7902e55ea42877910
#将 web100 容器的两个目录和新创建的 db1 容器共享
[root@tengxun-02 ~]#docker run -itd --volumes-from web100 --name db1 centos:7 /bin/bash
ac2cb6a53d98e2d0e80370da514fd7b7373729fcaa8e1c211df5faf288483a3f
[root@tengxun-02 ~]#docker ps -a
CONTAINER ID   IMAGE      COMMAND       CREATED          STATUS         PORTS     NAMES
ac2cb6a53d98   centos:7   "/bin/bash"   3 seconds ago    Up 2 seconds             db1
0f182c3e3a35   centos:7   "/bin/bash"   10 seconds ago   Up 9 seconds             web100
[root@tengxun-02 ~]#docker exec -it db1 bash
[root@ac2cb6a53d98 /]# ls /
anaconda-post.log  `data1`  dev  home  lib64  mnt  proc  run   srv  tmp  var
bin                `data2`  etc  lib   media  opt  root  sbin  sys  usr

六、容器互联

  • 容器互联是通过容器的名称在容器间建立一条专门的网络通信隧道。简单点说,就是会在源容器和接收容器之间建立一条隧道,接收容器可以看到源容器指定的信息。
docker run -itd -P --name web1 centos:7 /bin/bash	#创建并运行容器取名 web1,端口号自动映射
docker run -itd -P --name web2 --link web1:web1 centos:7 /bin/bash	#创建并运行容器取名 web2,链接到 web1 和其通信

> 进 web2 容器,ping web1

--link 的格式:
--link <name or id>:alias
其中,name 和 id 是源容器的 name 和 id,alias 是源容器在 link 下的别名。

七、端口映射

  • 在启动容器的时候,如果不指定对应的端口,在容器外是无法通过网络来来访问容器内的服务。端口映射机制将容器内的服务提供给外部网络访问,实际上就是将宿主机的端口映射到容器中,使得外部网络访问宿主机的端口便可访问容器内的服务。
[root@docker www]# docker run -d --name test1 -P nginx
0a07519f54de9552a37d076613f9f5af4ff4b80d1d3c258762c45f876a29500b
[root@docker www]# docker run -d --name test2 -p 11111:80 nginx
9316ffd9e2aa98e8d1ea679128d308fc0f1842d854e8b772c7cd5c07647251a8
[root@docker www]# docker ps -a
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                                     NAMES
9316ffd9e2aa   nginx     "/docker-entrypoint.…"   1 second ago     Up 1 second     0.0.0.0:11111->80/tcp, :::11111->80/tcp   test2
0a07519f54de   nginx     "/docker-entrypoint.…"   19 seconds ago   Up 18 seconds   0.0.0.0:49154->80/tcp, :::49154->80/tcp   test1

[root@docker www]# curl http://192.168.122.10:11111
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html {
      color-scheme: light dark; }
body {
      width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@docker www]# curl http://192.168.122.10:49154
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html {
      color-scheme: light dark; }
body {
      width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

八、Docker 镜像的创建

创建镜像有三种方法:

  • 基于已有镜像创建
  • 基于本地模板创建
  • 基于 Dockerfile 创建

8.1 基于现有镜像创建

启动一个镜像,在容器中做修改

[root@docker ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
nginx        latest    87a94228f133   28 hours ago   133MB
centos       7         eeb6ee3f44bd   3 weeks ago    204MB
[root@docker ~]# docker create -it --name test1 centos:7 bash
ae03a782eb8fed80190bfee1c5e459c1e82e1406a55627553e93edc943645217
[root@docker ~]# docker ps -a
CONTAINER ID   IMAGE      COMMAND   CREATED         STATUS    PORTS     NAMES
ae03a782eb8f   centos:7   "bash"    2 seconds ago   Created             test1

将修改后的容器提交为新的镜像,需要使用该容器的 ID 号创建新镜像

[root@docker ~]# docker commit -m "new" -a "centos" test1 centos:test1
sha256:3e6e91b628effd49a7fa8fea422057cb392c76e852b2d60f9d7287bfa172ff88
[root@docker ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
centos       test1     3e6e91b628ef   10 seconds ago   204MB
nginx        latest    87a94228f133   28 hours ago     133MB
centos       7         eeb6ee3f44bd   3 weeks ago      204MB

commit 常用选项:
-m:说明信息
-a:作者信息
-p:生成过程中停止容器的运行

8.2 基于本地模板创建

通过导入操作系统模板文件可以生成镜像,模板可以从 OPENVZ 开源项目下载,下载地址:
http://openvz.org/Download/template/precreated

[root@docker ~]# wget http://download.openvz.org/template/precreated/debian-7.0-x86-minimal.tar.gz
[root@docker ~]# cat debian-7.0-x86-minimal.tar.gz | docker import - debian:test
sha256:f7fd702b88cc14fbcc011dc0883edbf45dca3de99b0aef3fc8d184544c07fb5b
[root@docker ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED             SIZE
debian       test      f7fd702b88cc   36 seconds ago      215MB
centos       test1     3e6e91b628ef   About an hour ago   204MB
nginx        latest    87a94228f133   29 hours ago        133MB
centos       7         eeb6ee3f44bd   3 weeks ago         204MB

URL 下载方式:
方法一:
wget 下载路径 -O 保存路径
方法二:
curl -L 下载路径 -o 保存路径

载入选项:
通过 docker save 导出的镜像,使用 docker load 导入 docker
通过 docker export 导出的容器,使用 docker import 导入 docker

8.3 基于 dockerfile 创建

Docker 镜像创建之 — dockerfile 详解

你可能感兴趣的:(云计算,linux,linux运维,运维,docker,容器)