docker学习-docker入门

1 docker概述

1.1 docker简介

docker是dotcloud公司开源的一个基于LXC的高级容器引擎,源代码托管在github上,基于go语言编写并遵从apache2.0协议开源,主要是基于PAAS平台为开发者提供服务

容器是一种内核虚拟化技术,可以提供轻量级的虚拟化,以便隔离进程和资源

docker设想交付运行环境如同海运,OS如同一艘货轮,每一个在OS基础上的软件如同一个集装箱,用户可以通过标准化手段自由组装运行环境,同时集装箱内容可以用户自定义,也可以由专业人士制造

1.2 与传统虚拟化的区别

传统虚拟化技术

  • 优点:内核级别的隔离,安全性高
  • 缺点:操作系统资源浪费严重

容器化技术

  • 优点:轻量级、损耗少、启动快、性能高;
  • 缺点:容器安全性较差,应用程序本身没有隔离机制

1.3 docker自身组件

  • 官方镜像仓库:https://hub.docker.com/
  • docker client:Docker客户端
  • docker server:docker daemon的主要部分,接受用户通过Docker客户端发出的请求,并按照相应的路由规则分发
  • docker镜像:docker镜像运行后变成容器

1.4 docker安装

安装命令:curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
设置阿里云仓库:yum-config-manager
–add-repo
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
启动docker:systemctl start docker
检验是否安装成功:docker run hello-world
docker学习-docker入门_第1张图片

1.5 docker常用命令

docker pull:下载镜像
docker run:运行镜像
docker info:查看docker容器信息
docker search:docker仓库查询
docker pull:docker仓库下载
docker images:docker镜像查询
docker rmi:docker镜像删除
docker ps:容器查询
docker run:容器创建启动
docker start/stop:容器启动/停止
docker inspect:查看容器详情
docker logs:查看容器日志
docker stats:查看容器占用系统资源
docker exec:容器执行命令
docker exec -it 容器名 /bin/bash:登录容器bash

1.6 docker镜像特性

容器创建是需要指定使用的镜像,每个镜像都由唯一的标识Image ID,和容器的Container ID一样,他们默认都是128位,可以使用前16位作为缩略形式,也可以使用镜像镜像名和版本号两个部分组合成唯一表示,例如nginx:latest,如果省略版本号,默认使用的是最新版本标签,也就是latest,所以如果默认直接写nginx,其实系统执行的实际命令就是nginx:latest。

1.6.1 Docker 文件系统

Linux系统包含内核空间kernal和用户空间rootfs两部分,Docker容器只使用各自的rootfs但共用主机host的内核kernal,这样就产生了镜像结构分层。
rootfs是Docker容器在启动时内部进程可见的文件系统,也就是Docker容器的根目录。rootfs包含一个操作系统运行所需的文件系统。例如:可能包含典型类UNIX系统中的目录系统/dev/、/proc、/bin、/etc、/usr、/tmp…及运行Docker容器所需的配置文件、工具等。
docker学习-docker入门_第2张图片

  • rootfs
    在传统Linux内核启动时,首先会挂载一个只读的rootfs,当系统检测其完整性之后,再将其切换为读写模式。而在Docker架构中,当docker daemon为Docker容器改在rootfs时,会沿用Linux内核启动时的做法,也就是将rootfs设置为只读模式。当挂载完毕后,利用联合挂载union mount技术在已有的只读rootfs上再挂载一个读写层。这样,可读写的层处于Docker容器文件系统的最顶层,其下可能联合挂载了多个只读的层,只有在Docker容器运行过程中文件系统发生变化时,才会把变化的文件内容写到可读写层,并隐藏只读层中的旧版本文件
    docker学习-docker入门_第3张图片
    所有Docker容器都共用host主机的kernal内核。由于所有Docker容器都共用host主机的kernal内核,所以在容器中是不能对Linux内核kernal进行升级的。

2 dockerFile简介

Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。

2.1 FROM 和 RUN 指令的作用

FROM:定制的镜像都是基于 FROM 的镜像
RUN:用于执行后面跟着的命令行命令。有以下俩种格式
shell 格式:

  • shell 格式:

RUN <命令行命令>
<命令行命令> 等同于,在终端操作的 shell 命令。

  • exec 格式:

RUN [“可执行文件”, “参数1”, “参数2”]
例如:RUN ["./test.php", “dev”, “offline”] 等价于 RUN ./test.php dev offline

2.2 COPY 和 ADD 指令

  • COPY
    复制指令,从上下文目录中复制文件或者目录到容器里指定路径。
    格式:

COPY [–chown=:] <源路径1>… <目标路径>
COPY [–chown=:] ["<源路径1>",… “<目标路径>”]
[–chown=:]:可选参数,用户改变复制到容器内文件的拥有者和属组。
<源路径>:源文件或者源目录,这里可以是通配符表达式,其通配符规则要满足 Go 的 filepath.Match 规则。例如:

COPY hom* /mydir/
COPY hom?.txt /mydir/
<目标路径>:容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。

  • ADD
    ADD 指令和 COPY 的使用格类似(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:
  • ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>。
  • ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。

2.3 CMD

类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:

  • CMD 在docker run 时运行。
  • RUN 是在 docker build。

作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。

注意:如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。
格式:

CMD
CMD ["<可执行文件或命令>","","",…]
CMD ["","",…] # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数

推荐使用第二种格式,执行过程比较明确。第一种格式实际上在运行的过程中也会自动转换成第二种格式运行,并且默认可执行文件是 sh。

2.4 ENTRYPOINT

类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。
但是, 如果运行 docker run 时使用了 --entrypoint 选项,将覆盖 CMD 指令指定的程序。

  • 优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。
  • 注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。
    格式:

ENTRYPOINT ["","","",…]
可以搭配 CMD 命令使用:一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参,以下示例会提到。

示例:
假设已通过 Dockerfile 构建了 nginx:test 镜像:

FROM nginx
ENTRYPOINT [“nginx”, “-c”] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参

1 不传参运行

$ docker run nginx:test

容器内会默认运行以下命令,启动主进程。

nginx -c /etc/nginx/nginx.conf

2、传参运行

$ docker run nginx:test -c /etc/nginx/new.conf

容器内会默认运行以下命令,启动主进程(/etc/nginx/new.conf:假设容器内已有此文件)

nginx -c /etc/nginx/new.conf

2.5 ENV

设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。
格式:

ENV
ENV = =…

以下示例设置 NODE_VERSION = 7.2.0 , 在后续的指令中可以通过 $NODE_VERSION 引用:

ENV NODE_VERSION 7.2.0
RUN curl -SLO “https://nodejs.org/dist/v N O D E V E R S I O N / n o d e − v NODE_VERSION/node-v NODEVERSION/nodevNODE_VERSION-linux-x64.tar.xz”
&& curl -SLO “https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc”

2.6 ARG

构建参数,与 ENV 作用一致。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。
构建命令 docker build 中可以用 --build-arg <参数名>=<值> 来覆盖。
格式:

ARG <参数名>[=<默认值>]

2.7 VOLUME

定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。
作用:

  • 避免重要的数据,因容器重启而丢失,这是非常致命的。
  • 避免容器不断变大。
    格式:

VOLUME ["<路径1>", “<路径2>”…]
VOLUME <路径>
在启动容器 docker run 的时候,我们可以通过 -v 参数修改挂载点。

2.8 EXPOSE

仅仅只是声明端口。
作用:

  • 帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射。
  • 在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。
    格式:

EXPOSE <端口1> [<端口2>…]

2.9 WORKDIR

指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。(WORKDIR 指定的工作目录,必须是提前创建好的)。
docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。
格式:

WORKDIR <工作目录路径>

2.10 USER

用于指定执行后续命令的用户和用户组,这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)。
格式:

USER <用户名>[:<用户组>]

2.11 HEALTHCHECK

用于指定某个程序或者指令来监控 docker 容器服务的运行状态。
格式:

HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令
HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令
HEALTHCHECK [选项] CMD <命令> : 这边 CMD 后面跟随的命令使用,可以参考 CMD 的用法。

2.12 ONBUILD

用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜像的过程中不会执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这时执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令。
格式:

ONBUILD <其它指令>

2.13 LABEL

LABEL 指令用来给镜像添加一些元数据(metadata),以键值对的形式,语法格式如下:

LABEL = = = …

比如我们可以添加镜像的作者:

LABEL org.opencontainers.image.authors=“runoob”

3 仓库构建

3.1 仓库服务器配置

Registry 是一个开源的,无状态的(stateless),高可扩展的(highly scalable)服务器端应用,用来存储和获取你的分布式 Docker 镜像。
Registry 是一个存储(storage)和内容分发(content delivery)系统,持有命名的(named)Docker 镜像,通过使用不同的标签版本来区分。

  • 1 使用如下命令行来开始一个仓库容器:

$ docker run -d -v /opt/registry:/var/lib/registry -p 5000:5000 --restart=always --name registry registry

修改 daemon.json 文件
vim /etc/docker/daemon.json

{
“registry-mirrors”: [“https://yy28v837.mirror.aliyuncs.com”],
“insecure-registries”:[“192.168.243.128:5000”]
}
registry-mirrors 是配置的国内下载镜像的地址,因为默认拉取镜像是从国外地址拉取,导致下载镜像速度非常慢。
insecure-registries:[“宿主机ip:容器端口号”],配置安全端口

  • 2 重启 docker 服务

systemctl restart docker

  • 3 启动 registry 镜像

docker start localregistry

  • 4 上传镜像到私服
    打标签,标记镜像为私服仓库镜像

docker tag mynginx 192.168.243.128:5000/mynginx

查询镜像
在这里插入图片描述

  • 5 重启私服仓库

docker restart localregistry

  • 6 上传镜像到私服仓库

docker push 宿主机ip:私服容器端口号/镜像名

查询私服镜像
3 docker学习-docker入门_第4张图片

3.2 私服拉取镜像

私服仓库部署在 192.168.243.128 现在用192.168.243.129 服务器拉取私服仓库中的镜像

  • 1 配置私服仓库地址
    129 服务器修改配置文件 vim /etc/docker/daemon.json

{
“insecure-registries”:[“192.168.243.128:5000”]
}

  • 2 重启 docker 服务

systemctl restart docker

  • 3 拉取私服镜像

docker pull 192.168.243.128:5000/mynginx
docker学习-docker入门_第5张图片

  • 4 查询镜像

docker images
在这里插入图片描述

  • 5 启动容器镜像

docker run --name mynginx -p 80:80 -d 192.168.243.128:5000/mynginx
在这里插入图片描述

  • 6 查询镜像是否启动成功

docker ps
在这里插入图片描述

  • 7 浏览器访问 mynginx
    docker学习-docker入门_第6张图片

3 网络管理

3.1 网络通讯

docker学习-docker入门_第7张图片
本机安装并启动docker后会多一个docker0的网卡,可以理解为一个交换机。每启动一个容器,就会创建一个虚拟网卡和命名空间(vethX),容器和主机通过交换机通讯。
容器之间通过namespace隔离,隔离为两端,一端放在容器内部充当虚拟网卡,另一端放在宿主机上进行联通。不同容器间通过docker0网桥进行通讯

3.2 容器网络修改

-dns 用于指定启动容器的DNS
-net 用于指定网络的通讯方式,有四个值

  • bridge:docker默认方式,网桥模式
  • none:容器没有网络栈
  • container:使用其他容器的网络栈,docker容器会加入其他容器的network namespace
  • host:表示使用host网络,没有自己独立的网络栈,容器可以完全访问host,不安全
    docker学习-docker入门_第8张图片

3.3 网络隔离,独立ip配置

在同一个宿主机内,不同的docker容器默认工作在同一个网络域名命名空间内

3.3.1 通过网络命名空间实现隔离

查看当前可用网络类型:

[root@docker ~]# docker network ls
在这里插入图片描述

创建新的网络类型:docker network create -d 类型 网络空间名称

类型包括两种

  • overlay
  • bridge

docker学习-docker入门_第9张图片
指定网络空间启动容器
在这里插入图片描述
这样不同的容器就通过不同的网络空间实现隔离

3.3.2 配置网桥实现网络隔离

  • 配置网桥实现网络隔离的目的
    实现Docker宿主机的容器跨Docker宿主机的容器通信使用。
  • 配置网桥实现网络隔离原理
    将物理网卡桥接到创建的网桥网卡上;给网桥网卡配置IP地址;创建容器加载网桥网卡实现;docker宿主机容器跨docker宿主机容器通信;管理员管理docker宿主机通过网桥网卡进行远程管理
  • 配置docker网桥实现网络隔离
[root@centos01 ~]# vim /etc/sysconfig/network-scripts/ifcfg-ens32  
         <!--修改docker宿主机物理网卡桥接到网桥网卡br0-->
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static
DEFROUTE=yes
NAME=ens32
DEVICE=ens32
ONBOOT=yes
BRIDGE=br0    <!--添加此行-->
[root@centos01 ~]# cp /etc/sysconfig/network-scripts/ifcfg-ens32 /etc/sysconfig/network-scripts/ifcfg-br0   
         <!--创建并生成br0网桥-->
[root@centos01 ~]# vim /etc/sysconfig/network-scripts/ifcfg-br0 
TYPE=Bridge   <!--修改此行-->
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static
DEFROUTE=yes
NAME=br0      <!--修改名字-->
DEVICE=br0    <!--修改名字-->
ONBOOT=yes
IPADDR=192.220.130.10    <!--添加宿主机IP地址-->
NETMASK=255.255.255.0 
[root@centos01 ~]# systemctl restart network   
[root@centos01 ~]# ifconfig   
br0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.220.130.10  netmask 255.255.255.0  broadcast 192.168.100.255
 
br-0c69de4672ec: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.18.0.1  netmask 255.255.0.0  broadcast 0.0.0.0
 
br-35687468c903: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.19.0.1  netmask 255.255.0.0  broadcast 0.0.0.0
 
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 0.0.0.0
 
ens32: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        ether 00:0c:29:18:d3:26  txqueuelen 1000  (Ethernet)
 
ens34: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::4ad2:dd37:4341:5d8e  prefixlen 64  scopeid 0x20<link>
 
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
 
veth7b0bb5f: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::ccd3:86ff:fee6:5725  prefixlen 64  scopeid 0x20<link>
 
veth7e0f471: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::684c:fdff:fe13:b436  prefixlen 64  scopeid 0x20<link>
 
virbr0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 192.168.122.1  netmask 255.255.255.0  broadcast 192.168.122.255
[root@centos01 ~]# yum -y install git   
[root@centos01 ~]# git clone https://github.com/jpetazzo/pipework
            <!--下载docker容器网络管理工具pipework-->
[root@centos01 ~]# cp pipework/pipework /usr/local/bin/   
[root@centos01 ~]# chmod +x /usr/local/bin/pipework    
[root@centos01 ~]# docker run -d --name centos6.703 --network=none hub.c.163.com/public/centos:6.7-tools    
             <!--通过镜像运行容器-->
adea0ad48bdde947ec595382d96cba06eb6522ec046e9b3c7bfcb1edb5c84545
[root@centos01 ~]# pipework br0 centos6.703 192.168.100.101/24   
                   <!--给centos6.703容器配置IP地址-->
[root@centos01 ~]# docker exec -it centos6.703 /bin/bash   
[root@adea0ad48bdd /]# ifconfig    
eth1      Link encap:Ethernet  HWaddr FA:3A:9D:ED:C0:FF  
          inet addr:192.168.100.101  Bcast:192.168.100.255  Mask:255.255.255.0
[root@adea0ad48bdd /]# ping 192.168.220.130
PING 192.168.100.10 (192.168.220.130) 56(84) bytes of data.
64 bytes from 192.168.220.130: icmp_seq=1 ttl=64 time=0.100 ms
64 bytes from 192.168.220.130: icmp_seq=2 ttl=64 time=0.097 ms
64 bytes from 192.168.220.130: icmp_seq=3 ttl=64 time=0.039 ms

4 数据持久化

4.1 docker持久化的问题

docker学习-docker入门_第10张图片

Docker镜像由多个只读层叠加而成,启动容器时,Docker镜像会加载只读镜像层并在镜像顶部添加一个读写层。
如果运行中的容器修改了一个已经存在的文件,那么该文件会从读写层下面的只读层复制到读写层,该文件的只读版本仍然存在,只是已经被读写层中该文件的副本所隐藏,即写时复制的机制
docker容器关闭或重启,其数据不受影响。但是删除docker容器后,其改变的数据将全部丢失。
综上所述,docker容器存在的问题如下几点

  • 数据存在于联合文件系统中,不易于宿主机访问
  • 容器间数据共享不便
  • 删除容器其数据会丢失

4.2 卷

4.2.1 卷是什么

  • 卷是容器上的一个目录或多个目录,此类目录可以绕过联合文件系统,与宿主机上的某目录绑定
  • 卷可以在运行容器时即完成创建与绑定操作。当然,前提是拥有对应的声明
  • 卷的初衷就是数据持久化

docker学习-docker入门_第11张图片

4.2.2 卷的分类

docker学习-docker入门_第12张图片

  • bind mount volume:需要人为操作,输入一定的命令关联。可以是宿主机中的任何目录
    在这里插入图片描述

  • Docker-managed volume:需要人为设置,一旦引导转换为容器后,docker容器会字型管理。一般存在于/var/lib/docker下。

4.2.3 定义容器管理卷

  • 在dockerFile添加VOLUME选项
    docker学习-docker入门_第13张图片
  • 在容器内部创建若干文件
    docker学习-docker入门_第14张图片
  • 查看宿主机中目录
    在这里插入图片描述
  • 删除卷
    删除容器时候加一个 -v 即可
    在这里插入图片描述

5 资源限制

默认情况下docker容器是没有资源(内存、CPU)限制的,docker进程会尽可能榨干系统资源。正式的生产环境中容器资源都是会做限制的
Linux系统中经常有个需求就是希望能限制某个或者某些进程的所能使用的系统资源。比如:有分配好的特定比例的cpu时间,IO时间,可用内存大小等。于是就出现了cgroup的概念,cgroup就是control group,最初由google的工程师提出,后来被整合进Linux内核中。
Cgroup是Linux内核提供的一种可以限制、记录、隔离进程组所使用的物理资源的机制。它是将任意进程进行分组化管理的Linux内核功能。cgroup本身提供将进程进行分组化管理的功能和接口的基础结构

5.1 内存限制

docker学习-docker入门_第15张图片

5.2 CPU限制

docker学习-docker入门_第16张图片
docker学习-docker入门_第17张图片

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