Docker入门到上手部署

为什么要有Docker?

       开发与运维进行部署、协调时,开发需要清楚的告知运维团队,用的全部配置和相关的软件环境,这样也会有部署失败的情况,但很奇怪的是,代码在开发人员的环境是没有,在运维就出问题了,因此在排查此类问题就很耗费时间。

       在服务器上配置一个应用的运行环境需要安装各种软件,且还不能跨平台,在Windows安装了,在Liunx要重新安装,即便不跨操作系统,换一台机器的话,移植应用特别麻烦。

       运维如果部署多台机器时,需要部署多个相应的项目需要的所有软件。

       如果开发人员把项目所需要的相应软件都配置好并打成一个包给运维,而于屋内直接部署这个包就可以了,那就方便很多了,也不会出现开发和运维的环境不一致的问题。

       Docker就是为了解决以上的类似问题,提出的一个标准化解决方案。

 

 

Docker是什么?

       Docker是一个基于Go语言实现的开源项目,创始人是Solomon Hykes。

       Docker是在Liunx容器技术的基础上发展起来的,打破过去程序即应用的概念,通过镜像将作业系统核心除外的运作应用程序所需要的系统环境,由下而上打包(运行文档、配置环境、运行环境、运行依赖包、操作系统发行版、内核),达到应用程序跨平台间的无缝接轨、运行。,进而实现了跨平台、跨服务器、只需要一次配置好环境,换到别的机器上就可以一键部署好,大大简化了操作。

Docker的目标是Build Ship And Run Any App AnyWhere,也就是通过对应用组件封装、分发、部署、运行等生命周期的管理,使用户的应用及其运行环境能够做到一次封装、到处运行。

       Build(构建镜像) à Ship(运输镜像) à Run(运行镜像) à Any App(任何App) à Any Where(任何地方)

 

优点

一次构建、随处运行;

       轻量、秒级的快速启动应用,易于构建良好的RESTful API,也很适合自动化测试和持续集成,进而更快速的应用交付和部署;

       标准统一的打包、部署、运行,更简单的系统运维、升级、扩容;

       更高效的计算资源利用,基于容器虚拟化,仅包含业务运行所需的Runtime环境,CentOS/Ubuntu基础镜像仅170MB,宿主机可部署100 ~ 1000个容器;

       镜像支持增量分发、易于部署;

       活跃的社区;

 

缺点

       必须在64位机器上运行,只支持x86_64和AMD64,不支持32位系统,Liunx内核必须是3.8或以上;

       内核必须支持cgroups和命名空间;

       Docker的侵入式,增加了复杂的一层,让开发、调试、修复BUG变得复杂,经常创造很多问题,而不是解决问题,对于开发时,不带来显而易见的好处。

 

应用场景

       应用打包与部署自动化:物理机和虚拟机上部署运行环境时,面临环境杂乱、完整性迁移难度高;

       自动化测试和持续化集成、部署:自动化构建镜像和良好的RESTFul API,能够很好的集成到持续化集成部署环境来;

       部署与弹性扩展:容器是应用级的,资源占用小,弹性扩展、部署速度快;

       微服务:Docker的容器隔离技术,应对了微服务的理念,将业务模块放到容器中运行,加强了容器的可复用性;

 

核心技术

       cgroupsLiunx系统经常有个需求就是希望限制某个或某些进程的资源分配,于是就出现了cgroups概念,全称controller group,在这个group中有分配好的特定比例的cpu时间、io时间,后来被整合进Liunx内核中;cgroups中重要的概念是子系统,也就是资源控制器,每种子系统就是一个资源的分配器,如cpu子系统是控制cpu时间分配;分配的过程是首先要挂载子系统,然后才有controller groups的,比如先挂载memory子系统,然后在memory子系统中创建一个cgroup节点,在这个节点中,将需要控制的进程id写入,并且在控制的属性写入,这就完成了内存的资源限制;cgroups已被Liunx内核支持,在很多领域可以取代虚拟化技术分割资源技术,cgroups默认有诸多资源组,技术可以显示服务器上所有资源;

      

LXC全称是Liunx Containers,是一种基于容器的操作系统层级的虚拟化技术,借助namespace的隔离机制和cgroups限制功能,LXC提供了一套统一的API和工具来建立和管理container;LXC跟其他操作层级的虚拟化技术相比,最大的优势在于LXC被整合进内核,不用单独为内核打补丁;LXC旨在提供一个贡献Kernel的OS级虚拟化方法,在执行时不用重复加载Kernel,且container的Kernel与host共享,因此可以大大加快container的启动过程,并显著减少内存消耗,容器在提供隔离的同事,还通过共享这些资源节省开销,这意味着容器壁真正的虚拟机开销要小的多;

性能:LXC > KVM > XEN

内存利用率:LXC > KVM > XEN

隔离程度:XEN > KVM > LXC

       AuFS能透明覆盖一或多个现有文件系统的层状文件系统,支持将不同目录挂在同一个虚拟文件下,可以把不同目录联合在一起,组成一个单一的目录,这是一种虚拟的文件系统,文件系统不用格式化,直接挂载即可;Docker一直在用AuFS作为容器的文具系统,当一个进程需要修改一个文件时,AuFS创建该文件的一个副本,AuFS可以把多层合并成文件系统的单层表示,这个过程称为写入复制(copy or write);还允许Docker把某些镜像作为容器的基础,因此可以有一个开源作为很多不同容器的基础的CentOS的系统镜像,因此节省了存储和内存,也保证更快速的容器部署;使用AuFS的另一个好处是Docker的镜像能力,每个新版本都是一个与之前版本的简单差异改动,有效保持镜像文件最小化,但也意味着总需要有一个记录该容器从一个版本到另一个版本的改动审计跟踪;

 

基本组成

       Image(镜像):就是一个只读模板,可以用来创建Docker容器,一个镜像可以创建多个容器;

       Container(容器):独立运行的一个或一组应用,容器是用镜像创建的运行实例;容器可以被启动、开始、停止、删除,每个容器都是相互隔离的,保证安全的平台;可以把容器看做是一个简易版的Liunx环境(包括root用户权限、进程空间、用户空间和空间等)和运行在其中的应用程序;容器的定义和镜像几乎一模一样,也是一对层的统一视角,唯一区别在于容器的上面一层是可读可写的;

       仓库(Repository):集中存放镜像文件的场所;包括仓库和仓库注册器,仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同标签(TAG);仓库分为公开仓库(Docker Hub)和私有仓库两种形式;

       Docker Daemon创建和运行Container的Liunx守护进程,也是Docker最主要的核心组件;理解理解为Docker Container的Container;可以绑定本地端口并提供RESTful API服务用来远程访问和控制;

 

       小结:

Docker本身是一个容器运行载体或管理引擎,把应用程序和配置依赖打包好形成一个可交付的运行环境,这个打包好的运行环境就类似Image镜像文件,只有通过这个镜像文件才能生成Docker容器,Image文件可以看做是容器的模板,Docker根据Image文件生成容器的实例,同一个Image文件,可以生成多个同事运行的容器实例;

       Image文件生成的容器实例本身也是一个文件,称为镜像文件;一个容器运行一种服务,当我们需要的时候,就可以通过Docker 客户端创建一个对应的运行实例,也就是我们的容器仓储,就是放了一堆镜像的地方,把镜像发布到仓储,需要时从仓储拉下来即可;

 

 

Docker安装

安装条件

CentOS 6.5(64 Bit)或更高版本,系统内核版本为2.6.32-431或更高版本;

 

#查看操作系统内核版本号(内核版本号、硬件架构、主机名称、操作系统类型等)

       uname -r

       #查看操作系统版本

       cat /etc/redhat-release

 

Centos 6.8安装

       # Dcoker用EPEL发布,RHEL系OS要先确保已经有EPEL仓库并安装

       yum install -y epel-release

       #正式安装Dcoker

       yum install -y docker-io

 

       注:在安装时出现Error: Cannot retrieve metalink for repository: epel. Please verify its path and try again错误, vi /etc/yum.repos.d/epel.repo 将baseurl注释取消,将mirrorlist注释掉

 

       #安装完成后的配置文件

       cat /etc/sysconfig/docker

#启动docker后台服务

       service docker start

       #验证是否成功

       docker version

 

       #配置镜像加速器:http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

vi /etc/sysconfig/docker

 

       #重启docker

service docker restart

 

       #查看是否配置了镜像加速

       ps -ef | grep docker

 

Centos 7安装

       官方文档:https://docs.docker.com/install/linux/docker-ce/centos/

      

       yum -y install gcc

yum -y install gcc-c++

gcc -v

#卸载老版本

       yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine

       #安装需要的软件包

yum install -y yum-utils device-mapper-persistent-data lvm2

 

       #配置连接仓库

       #这个是链接外网的

       yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

       #这个是使用国内阿里云(建议使用)   

       yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

 

       #更新yum软件包

yum makecache fast

#安装docker ce

yum -y install docker-ce

yum install docker-ce docker-ce-cli containerd.io

 

#启动docker

systemctl start docker

 

#配置阿里云镜像加速https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors

mkdir -p /etc/docker

vim /etc/docker/daemon.json

 

#重启docker

systemctl reload docker(重新加载配置文件,不会中断服务)

systemctl docker restart(会先stop后在start,会重启服务)

 

       #查看是否配置了镜像加速

       ps -ef | grep docker

 

测试

       #以docker的方式运行一个叫hello-world的镜像,仔细看运行过程日志

       docker run hello-world

 

 

Docker运行原理

       Docker是一个Client-Server结构的系统,Docker守护进程运行在主机上,然后通过Socker连接从客户端访问,守护进程从客户端接受命令并管理运行在主机上的容器,容器是一个运行时环境。

 

与虚拟机的区别

       虚拟机(Virtual Machine)就是带环境安装的一种解决方案;虚拟机可以在一种操作系统里面运行另一种操作系统,比如在Windows系统运行Liunx系统,应用程对此毫无感知,因虚拟机看上去跟真实操作系统一模一样,而对于底层系统来说,虚拟机就是一个普通文件,不需要了就删除,对其他部分毫无影响,这类虚拟机完美的运行了另一套系统,能够使应用程序,操作系统和硬件三者之间的逻辑不变;

       虚拟机的缺点就是资源占用多、冗余步骤多、启动慢,因此Liuynx发展出另一种虚拟化技术,就是Liunx容器(Liunx Containers,缩写是LXC)。

       Liunx容器不是模拟一个完整的操作系统,而是对进程进行隔离,有了容器就可以将软件运行所需的所有资源打包到一个隔离的容器中;容器与虚拟机不同,不需要捆绑一整套操作系统,只需要软件工作所需的库资源和设置,系统因此变得高效、轻量并保证部署在任何环节中的软件都能始终如一的运行。

传统虚拟化技术是虚拟出一套硬件后,在其上运行一个完整的操作系统,在该系统上运行所需要的应用进程;

       Docker容器内的应用程序直接运行于宿主机的内核,容器没有自己的内核,且也没有进行硬件虚拟,因此容器要比传统虚拟机更为轻便;

       Docker每个容器之间互相隔离,每个容器有自己的文件系统,容器之间不会相互影响,能区分计算资源;

 

       Docker为什么比虚拟机快?

       Docker不需要Hypervisor实现硬件资源虚拟机化,运行在Docker容器上的程序直接使用的都是实际物理机的硬件资源,从而Docker有着比虚拟机更少的抽象层,因此在CPU、内存利用率上Docker将会在效率上有明显优势。

       Docker利用的是宿主机的内存,不需要GuestOS,因此当新建一个容器时,Docker不需要和虚拟机一样重新加载一个操作系统内核,从而避免引寻、加载操作内核这些比较耗时、耗资源的过程,当新建一个虚拟机时,虚拟机软件需要加载GuestOS,新建过程是分钟级别的,而Docker是直接利用宿主机的操作系统,省略了整个过程,因此新建一个Docker容器只需要几秒钟。

 

 

Docker

虚拟机

系统

共享宿主机

宿主机上运行虚拟机OS

存储

镜像小,便于存储和传输

镜像庞大(vmdk、vid…)

性能

几乎无额外性能损失

额外的CPU、内存消耗

移植

轻便、灵活、适应于Liunx

笨重,与虚拟化技术耦合度高

对象

软件开发者

硬件运维者

 

注:在docker中拉取下来一个centos镜像时,会发现很多命令丢失,因只留下内核相关的内容,所以也只有几百MB。

 

 

Docker常用命令

帮助命令

       #docker版本

       docker version

      

#docker信息描述

       docker info

      

       #命令帮助

       docker --help

 

镜像命令

       #列出本地的镜像列表(repository镜像仓库源或名称、TAG镜像标签、image id镜像id、created 镜像创建时间、size 镜像大小)

       #同一个仓库源有多个TAG,代表这个仓库源的不同版本,使用REPOSITORY:TAG来定义不同镜像,如果不指定一个镜像的版本标签,例如使用ubuntu,docker将默认使用ubintu:latest镜像,默认版本是最新。

docker images

      

       #列出本地所有的镜像,包含中间映像层

       docker images -a

 

       #只显示镜像ID

       docker images -q

      

       #显示镜像的摘要信息

       docker image --digests

 

       #显示完整的镜像信息

       docker images –no-trunc

 

       #显示所有镜像的ID

       docker images -qa

 

       #搜索镜像,docker search tomcat

       #公开镜像仓库地址:https://hub.docker.com/

       docker search 镜像名

 

       #显示完整的镜像描述

       docker search --no-trunc 镜像名

 

       #列出收藏数不小于指定数的镜像(start列是收藏数)

       docker search -s 数值 镜像名

 

       #只列出automated build类型的镜像,即自动化操作的镜像

       docker search --automated 镜像名

 

       如:docker search -s 20 --automated --no-trunc centos

 

       #从仓库拉取某个镜像,默认是最新版本,docker pull 镜像名 = docker pull 镜像名:latest

       docker pull 镜像名

      

       #从仓库拉取某个镜像的指定版本,docker pull tomcat:8.5

       docker pull 镜像名:版本号

 

       #删除镜像,没有写TAG,默认是latest,即最新版本

       docker rmi 镜像名

       docker rim 镜像名:TAG

 

       #强制删除,如镜像内还有一层或有容器在运行就无法删除,那么则要强制删除

       docker rmi -f 镜像名

 

       #删除多个

       docker rmi -f 镜像名1 镜像名2

 

       #先用docker images -q查询出本地仓库的容器,删除查询出的结果

       docker rmi -f $(docker images -q)

 

容器命令                                                   

       #新建并启动容器

       docker run [OPTIONS] image [COMMAND] [ARG…]

              OPTIONS参数:

                     --name 容器名称:为容器指定一个名称,没有指定就默认

                     -d:守护式进程启动运行容器,并返回容器ID

                     -i:以交互式模式运行容器,通常与-t同时使用

                     -t:为容器重新分配一个伪输入终端,通常与-i同时使用

                     -P:随机端口映射

                     -p:指定端口映射;有四种格式,ip:hostPort:containerPort、ip::containerPort、hostPort:containerPort、containerPort

 

       #以交互式模式启动一个容器

       docker run -it 镜像Id

       docker run -it centos

       docker run -it --name 容器名 镜像名

       docker run -it --name centos2 centos

 

       #使用镜像centos:latest以交互式模式启动一个容器,在容器内支撑/bin/bvash命令

       docker run -it centos /bin/bash

 

       #以守护式进程的方式启动,即不进入交互模式,使用docker ps是没有容器,docker ps -a一看,会发现容器的状态是已经退出了;这涉及到Docker的一个机制,Dcoker容器后台运行就必须有一个前台进程,容器运行的命令如果不是那些一直挂起的命令(如top、tail)就会自动退出;如nginx容器,正常情况下,配置启动服务只需要service nginx start,但这样做,nginx为后台进程模式运行,就导致docker前台没有运行的应用,这样的容器后台启动后会自动停止,因此容器觉得没有事情做了,所以最佳解决方案就是将要运行的程序以前台进程形式进行;

       docker run -d centos

 

       #列出容器

       docker ps [OPTIONS]

              OPTIONS:

                     -a:列出当前所有正在运行的容器+历史运行过的

                     -l:显示最近创建的容器

                     -n:显示最近n个创建的容器

                     -q:静默模式,只显示容器编号

                     --no-trunc:不截断输出

 

       #查看所有容器

       docker ps

 

       #显示2个容器

       docker ps -n 2

 

       #容器停止并退出

       exit

 

       #容器不停止退出

       Crtl+P+Q

 

       #启动容器

       docker start 容器id

 

       #重启容器

       docker restart 容器id

 

       #停止容器

       docker stop 容器id或容器名

      

       #强制关闭容器

       docker kill 容器id或容器名

      

       #删除容器

       docker rm 容器id

 

       #强制删除容器

       docker rm -rf 容器id

 

       #根据查询结果进行删除

       docker rm -rf $(docker ps -qa)

 

       #删除多个容器

       docker ps -a -q | xargs docker rm

 

       #查看容器日志

       docker logs -f -t --tail 数值 容器id

              -t:加入时间戳

              -f:跟随最新的日志打印

              --tail:数字,显示最后多少条

      

##测试

       docker run -d centos /bin/sh -c “while true;do echo hello;sleep2;done”

       docker logs -f -t --tail=all 容器id

       docker logs -f -t --tail 10 容器id

      docker logs -f -t --tail all 容器id

 

       #查看容器内的进程

       docker top 容器id

 

       #查看容器详细信息

       docker inspect 容器id

 

       #重新进入容器

       docker exec -it 容器id /bin/bash

      

       #直接运行命令

       docker exec -it 容器id ls -a

 

       #重新进入docker容器

       #atttach是直接进入容器启动命令的终端,不会启动新的进程,exec是在容器内打开新的终端,并且可以启动新的进程;

       docker attach 容器id

      

       #复制容器内文件到宿主机上

       docker cp 容器id:容器内路径 宿主机路径

       docker cp 容器id:/tmp/test.txt ~

 

 

Docker镜像

       镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,包含运行某个软件所需要的所有内容,包括代码、运行时库、环境变量和配置文件等…

       镜像实际是UnionFs(联合文件系统)的缩写,是一种分层、轻量级、高性能的文件系统,支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂在同一个虚拟文件系统下(unite serveral directiories into a single virtual filesystem),union文件系统是Docker镜像的基础,镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

 

特性

       一次同时加载多个文件系统,但从外面看起来只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层文件和目录。

       Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部,这一层通常被称作容器层,容器层之下都叫镜像层。

 

加载原理

       Docker的镜像实际是由一层层的文件系统组成,这种层级的文件系统UnionFS。

       bootfs(boot file system)主要包含bootloader和kernel,bootloader主要是引导加载kernel,Liunx刚启动时会加载bootfs文件系统,在Docker镜像的最底层就是bootfs,这一层与Liunx/Unix系统是一样的,包含boot加载器和内核,当boot加载完成之后整个内核就都在内存中了,此时内存使用权已由bootfs转交给内核,此时系统也会写在bootfs。

       rootfs(root file system)在bootfs之上,包含的就是Liunx系统中的/dev、/proc、/bvin、/etc等标准目录和文件,rootfs就是各种不同的操作系统发行版,比如Ubuntu、CentOS等;这也是为什么平时的centos有几个G,docker的centos镜像只有几百MB,对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用Host的Kernel,自己只需要提供rootfs就可以了,由此可见对于不同的Liunx发行版,bootfs基本是一直的,rootfs会有差别,因此不同的发行版可以用共用的bootfa;

 

镜像分层

       如:tomcat镜像包含:tomcat -> jdk -> centos

       有很多镜像都是从相同的base镜像构建而来的,那么宿主机只需要在磁盘上保存一份base镜像,内存中也只需要加载一份base镜像,就可以为所有容器服务了,而且镜像的每一层都可以被贡献,进而达到资源共享的目的。

 

docker commit

       docker commit 提交容器副本,使之成为一个新的镜像,如修改tomcat的配置等。

 

       #语法

       docker commit -a=”作者” -m=”描述信息” 容器id 要创建的目标镜像名:标签名

 

案例:

# 运行tomcat

Docker run -it -p 宿主机端口:容器端口 tomcat

       Docker run -it -p 9998:8080 tomcat

 

       #随机分配宿主机端口

       Docker run -it -P tomcat

 

#浏览器访问

       localhost:9998

 

       #可以看到第一个是宿主机端口,第二个是容器内的端口

       docker ps

 

       #删除容器中的tomcat的webapp的docs文件夹,此时在浏览器中点击documention是看不到了

       docker exec -it 容器id /bin/bash

       cd webapps

       rm -rf docs

 

       #当前这个tomcat的实例是一个没有文档内容的容器依次为模板,commit一个没有doc的tomcat容器为新镜像

 

       docker ps

       docker commit -a “test” -m “test” 容器id 新镜像名:TAG

       docker images

       docker run -d –name mytomcat -p 9990:8080 新镜像名:TAG

      

       #浏览器访问,查看doc还在不在

       Localhostr:9990

      

 

 

Docker容器数据卷

       将运行与运行的环境打包形成容器运行,运行可以伴随着容器,但对数据的要求是希望持久化的,并且容器之间可以共享数据。

       Docker容器产生的数据,如果不通过docker commit 生成新的镜像,使数据作为镜像的一部分保存下来,那么当容器删除后,数据自然也就没了,为了能够保存数据在docker中,就要使用卷了。

       卷是目录或文件,存在于一个或多个容器中,由Docker挂载到容器中,但不属于联合文件系统,因此能够绕过Union File System提供一些用于持续存储或共享数据的特性。

       卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会再容器删除时删除其挂载的数据卷。

 

特点

       可在容器之间、主机与容器之间共享或重用数据

       卷中的更改可以直接生效

       数据卷中的更改不会包含在镜像的更新中

       生命周期一直持续到没有容器使用为止

 

操作

案例一:使用-v添加卷

       #创建容器时,创建卷,-v带有自建目录(文件夹)的功能

       Docker run -it -v /宿主机目录:/容器内目录 镜像名

 

       #此命令是带有权限的,ro即容器内对这个卷目录是只读不可写

       docker run -it -v /宿主机目录:/容器内目录:ro 镜像名

      

       #此命令是带有权限的,ro即容器内对这个卷目录是可读可写

       docker run -it -v /宿主机目录:/容器内目录:rw 镜像名

 

       docker run -it --name mycentos -v /htest:/test centos

       #可以看到挂载的卷信息

docker inspect

       cd test

       touch test.txt

       vi test.txt

       退出容器

       cd htest/

       cat test.txt

       rm -rf test.txt

       docker exec -it 容器id /bin/bash

       ll test

       rm -rf iii.txt

       ll test

       退出容器

      

       #在容器中删除了,宿主机也会删除,同理。

      

 

案例二:使用DockerFile添加卷

       mkdir /mydocker

       cd /myudocker

       vi dockerfile

       -----------------------------

FROM centos

VOLUME ["/test1","/test2"]

CMD echo "finished ----------"

CMD echo /bin/bash

       -----------------------------

       #构建dockerfile文件,构成新的镜像

       docker build -f dockerfile -t mycentos:latest .

       docker images

       #运行镜像

       docker run -it mycentos /bin/bash

       #查看卷的位置

docker inspect 容器id

       docker exec -it 容器id /bin/bash

 

       注:在Docker数据卷挂在宿主机目录时,访问出现没有权限的错误是,可以在挂在的目录中多加一个—privileged true的参数即可;如:docker run -it -v /test:/test --privileged=true centos

 

 

案例三:父数据卷

       容器挂载数据卷,其他容器通过挂载这个(父容器)实现数据贡献,挂载数据卷的容器称之为数据卷容器。

      

       #语法

       docker run -it --name 容器名称 --volumes -from 容器名称 镜像名称:TAG /bin/bash

 

       docker run -it –name dc0 centos -v /test:/test /bin/bash

       docker ps

       docker run -it –name dc1 dc0:latest /bin/bash

       docker ps

       docker run -it –name dc2 --volumes-from dc1 centos:latest /bin/bash

       ll /test

       touch /test/dc2.txt

       #退出容器

       #进入容器1进行查看

       #删除容器1

       docker run -it --name dc3 --volumes-from dc2 centos:latest /bin/bash

       ll /test

       touch /test/dc3.txt

       #进入容器2查看,删除容器2

      

       #结论:容器之间配置信息的传递,数据卷的生命周期一直持续到没有容器使用为止。

 

 

DockerFile

       用来构建Docker镜像的构建,是由一系列的命令和参数构成的脚本

 

构建步骤

       编写dockerfile文件 à docker build à docker run

 

Base镜像

       scratch是一个源镜像,即基础镜像,类似java的Object,Docker Hub中99%的镜像都是通过在base镜像中安装和配置西药的软件构建出来的。

 

基础内容

       每条保留字指令必须大写字母,且后面跟随至少一个参数;

       指令按照从上到下,顺序执行;

       #表示注释;

       每条指令都会创建一个新的镜像层,并对镜像进行提交;

 

执行流程

       从基础镜像运行一个容器,即祖先镜像scratch;

       执行一条指令并对容器做出修改

       执行类似docker commit操作提交一个的镜像层;

       docker在基于提交的镜像运行一个新的容器;

       执行dockerfile中的下一条指令直到指令都执行完成;

 

小结

       DockerFile、Docker镜像与Docker容器分别代表软件的三个不同阶段。

 

       DockerFile是软软件的基础组成,面向开发,相当于云平台的laas层(基础服务层)

       Docker镜像是软件成品、交付标准,相当于云平台的PasS层(平台服务层)

       Docker容器是软件的运行形态、部署与运维,相当于云平台的SaaS层(软件服务)

 

常用保留字指令

       FROM基础镜像,当这个镜像是来自哪个镜像的;

       MAINTAINER镜像维护者的姓名和邮箱地址;

       RUN容器构建时运行的命令

       EXPOSE当前容器对外暴露出的端口,即位于宿主机的端口号;

       WORKDIR指定在创建容器后,终端默认登录进来的工作目录,即落脚点

       ENV用来构建镜像过程中设置环境变量;这个环境变量可以在后续的任何RUN指令中使用,这也就如同在命令前面指定了环境变量前缀一样,也可以在其他指令中直接使用这些环境变量;

       ADD将宿主机目录下的文件拷贝进镜像,且会自动处理URL和解压tar压缩包;

       COPY类似ADD,拷贝文件和目录到镜像中,将从构建上下文件目录中源路径的文件/目录复制到新的一层的镜像内(目标路径)的位置,如COPY src desc、COPY [“src”,”desc”];

       VOLUME容器数据卷,用于数据保存和持久化工作,但不能指定对应的宿主机地址,采用的宿主机默认地址;

       CMD指定一个容器启动时要运行的命令,DockerFile中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换。

       ENTRYPOINT指定一个容器启动时要运行的命令,ENTRYPOINT的目的和CMD一样,都是在指定容器启动程序及参数,在docker run之后的参数不会替换和覆盖,且会追加并会提交、执行;

       ONBUILD当构建一个被继承的Dcokerfile时运行命令,父镜像在被子继承后,父镜像的onbuild被触发;

 

操作

案例一:自定义镜像centos

       mkdir /mydocker

       vi mycentos.dockerfile

       -------------------------------------

       #指定镜像

       FROM centos

       #作者

       MAINTAINER levi[email protected]

       #环境变量

       ENV MYPATH /tmp

       #落脚点

       WORKDIR $MYPATH

       #运行命令(容器构建时运行)

       RUN yum -y install vim

       RUN yum -y install net-tools

       #容器对外暴露端口

       EXPOSE 80

       #命令(容器启动时运行)

       CMD echo $MYPATH

       CMD echo “success”

       CMD /bin/bash

       -------------------------------------

       docker build -f /mydocker/mycentos.dockerfile -t mycentosdoc:1.0

       docker images

       docker history 镜像名

       docker run -it mycentosdoc:1.0

 

案例二:CMD-ENTRYPOINT命令

       #查看docker hub的tomcat的dockerfile

#会看到有输出日志,Tomcat也可以访问

       docker run -it -p 8888:8080 tomcat

 

       #会看到输出目录,最后一行的run也没有执行了,tomcat也没有运行了

       docker run -it -p 8888:8080 tomcat ls l

 

       vi /mydocker/cmd.dockerfile

       -------------------------------------

       #指定镜像

       FROM centos

       #运行命令

       RUN yum install -y curl

       #查询ip

       CDM [“curl”,”-s”,”http://ip.cn”]

       -------------------------------------

       docker build -f /mydocker/cmd.dockerfile -t myip .

       docker images

       docker run -it myip

       #此时出现的是报错,跟在镜像名后面的是command,运行时会替换掉CMD的默认值,一次你这里的-i替换掉原有的CMD,而不是添加在curl -s http://ip.cn后面,而-i根本不是命令,因此报错找不到

       docker run -it myip -i

       #正确

       docker run -it myip curl -s -I http://ip.cn

 

       vi /mydocker/entrypoint.dockerfile

       -------------------------------------

       #指定镜像

       FROM centos

       #运行命令

       RUN yum install -y curl

       #查询ip

       #CDM [“curl”,”-s”,”http://ip.cn”]

       ENTRYPOINT  [“curl”,”-s”,”http://ip.cn”]

       -------------------------------------

       docker build -f /mydocker/entrypoint.dockerfile -t entrypoint:latest .

       docker run -it entrypoint

       #此时会看到不会报错了,因为此时是追加

       docker run -it entrypoint -i

 

案例三:ONBUILD命令

       vi /mydocker/onbuild.dockerfile

       -------------------------------------

       #指定镜像

       FROM centos

       #运行命令(构建时运行)

RUN yum install -y curl

#运行命令

       ENTRYPOINT  [“curl”,”-s”,”http://ip.cn”]

       #只要有子镜像继承了父镜像就会输出此话

       ONBUILD RUN echo “build ----------------”

       -------------------------------------

 

       docker build -f /mydocker/onbuild.dockerfile -t onbuild:latest .

      

       vi /mydocker/onbuild-son.dockerfile

       -------------------------------------

       #指定镜像

       FROM onbuild

       #运行命令(构建时运行)

RUN yum install -y curl

#运行命令

       ENTRYPOINT  [“curl”,”-s”,”http://ip.cn”]

       -------------------------------------

 

       docker build -f /mydocker/onbuild-son.dockerfile -t onbuild_son:latest

      

       #看日志

 

案例四:自定义Tomcat

       #在/mydocker目录下存在以下这个2个文件

       apache-tomcat-8.5.16.tar.gz

       jdk-8u131-linux-x64.tar.gz

 

       vi /mydocker/tomcat.dockerfile

       -------------------------------------

       #指定镜像

       FROM centos

       #作者信息

       MAINTAINER levi<[email protected]>

       #宿主机的文件拷贝到容器内

       COPY copy.txt /usr/local/copy.txt

       #把JDK和tomcat添加到容器

       ADD jdk-8u131-linux-x64.tar.gz /usr/local

       ADD apache-tomcat-8.5.16.tar.gz /usr/local

       #安装vim编辑器

       RUN yum -y install vim

       #设置工作访问时的落脚点

       ENV MYPATH /usr/local

       WORKDIR $MYPATH

       #配置Java和Tomcat变量

       ENV JAVA_HOME /usr/local/jdk1.8.0_131

       ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

       ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.16

       ENV CATALINA_BASE /usr/local/apache-tomcat-8.5.16

       ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_BASE/bin

       #容器运行时,对宿主机暴露的端口

       EXPOSE 8080

       #启动时,运行tomcat

       #ENTRYPOINT ["/usr/local/apache-tomcat-8.5.16/bin/startup.sh"]

       #CMD ["/usr/local/apache-tomcat-8.5.16/bin/startup.sh"]

       CMD /usr/local/apache-tomcat-8.5.16/bin/startup.sh && tail -f /usr/local/apache-tomcat-8.5.16/logs/catalina.out

       -------------------------------------

 

       docker build -f /mydocker/tomcat.dockerfile -t mytomcat:latest .

       docker run -d -p 9999:8080 --name mytomcat -v /test/logs:/usr/local/apache-tomcat-8.5.16/logs -v /test/html:/usr/local/apache-tomcat-8.5.16/webapps/test --privileged=true mytomcat

 

       #浏览器访问localhost:9999

 

案例五:发布内容到Tomcat

       cd /test

       vi test.html

       -------------------------------------

       <h1>Ttest</h1>

       -------------------------------------

      

       #浏览器访问localhost:9999/test/test.html

       #实现一次发布,多个容器起作用

 

 

Docker安装软件

步骤

       搜索镜像

       拉取镜像

       查看镜像

       启动镜像

       停止容器

       移除容器

 

安装Mysql

       docker images

       docker search mysql

       docker pull mysql:5.6

       docker images

       #运行Myslq,-d后台服务运行为mysql5.6,-e初始化root用户密码,即环境变量

       docker run -p 12345:3306 -v /docksoft/mysql/conf:/etc/mysql/conf.d -v /docksoft/mysql/logs:/logs -v /docksoft/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.6

       docker ps

       docker exec -it 容器id /bin/bash

       pwd

       mysql -uroot -p

 

       MySQL备份:docker exec -it 9c201452821f mysqldump --all-databases -uroot -p"123456" > /dockersoftware/mysql/databases.sql

 

安装Redis

       docker images

       docker search redis

       docker pull redis

       docker run -p 6379:6379 -v /docksoft/redis/data:/data -v /docksoft/redis/conf/redis.conf:/usr/local/etc/redis/redis.conf -d redis:3.2 redis-server /usr/local/etc/redis/redis.conf --appendonly yes

       docker exec -it 容器id redis-cli

       set a b

       get a

 

Docker仓库

推送镜像到阿里云仓库

       到阿里云创建一个镜像仓库https://cr.console.aliyun.com/cn-shenzhen/instances/repositories

       看阿里云文档

 

搭建私有仓库

       Docker Hub是Docker默认官方公共镜像仓库,搭建私有镜像仓库的话,官方也提供了registry镜像,使得搭建私有仓库非常简单。

      

       docker search registry

       docker pull registry

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

       #查看仓库的所有镜像

       curl http://localhost:5000/v2/_catalog

       #配置私有仓库可信任

       vi /etc/docker/daemon.json

       -------------------------------------

{"insecure-registries":["公网地址:5000"]}

       -------------------------------------

systemctl restart dockr

 

#给镜像打标签

docker tag centos:latest 公网地址:5000/mycentos:1.0

#上传镜像

docker push 公网地址:5000/mycentos:1.0

#下载镜像
       docker pull 公网地址:5000/mycentos:1.0

       #下载

       docker pull 公网地址:5000/mycentos:1.0

       列出镜像标签

       curl http://localhost:5000/v2/mycentos/tag/list

 

Harbor

       VMWare公司开源的企业级Docker容器镜像私有仓库,以Docker Registry为基础进行相应的企业级扩展,从而获得了更广泛的应用,这些新特性包括管理用户界面、基于角色的访问控制/LDAP继承及审计日志等,同时还支持原生中文,每个组件都是以Docker容器的形式构建的,用于部署Harbor的Docker Compose模板位于/Deployer/docker-compose.yml,由5个容器组成,这几个容器通过Docker Link的形式连接在一起,在容器之间通过容器名字互相访问,对终端用户而言,只需要暴露Proxy(Nginx代理)的服务端口。

       说白了,就是在Docker Registry基础上增了UI和权限控制的私有仓库。

 

核心组件

       ProxyNginx服务器构成反向代理;

       Registry由Docker官方的开源Registry镜像构成容器实例;

       UIB/S架构的Web界面;

       Service构成此容器的代码,也是Harbor项目的主体;

       MySQL官方MySQL镜像构成的数据库容器;

       Log运行着rsyslogd的容器,通过log-driver的形式和其他容器的日志;

 

安装条件

       Python为2.7或以上版本

       Docker引擎为1.10或以上版本

       Docker Compose为1.6.0或以上版本

安装

1、解压软件包: tar xvf harbor-offline-installer-<version>.tgz

       https://github.com/vmware/harbor/releases/download/v1.2.0/harbor-offline-installer-v1.2.0.tgz

       2、配置harbor.cfg

              a、必选参数

                     hostname:目标的主机名或者完全限定域名

                     ui_url_protocol:http或https,默认为 。默认为http

                     db_password:用于db_auth的MySQL数据库的根密码。更改此密码进行任何生产用途

                     max_job_workers:(默认值为3)作业服务中的复制工作人员的最大数量。对于每个映像复制作业,工作人员将存储库的所有标签同步到远程目标。增加此数字允许系统中更多的并发复制作业。但是,由于每个工作人员将存储库的所有标签同步到远程目标。增加此数字允许系统中更多的并发复制作业。但是,由于每个工作人员都会消耗一定数量的网络/CPU/IO资源,请根据主机的硬件资源,仔细选择该属性的值资源,请根据主机的硬件资源,仔细选择该属性的值

                     customize_crt:(on或off,默认为on)当此属性打开时,prepare脚本将为注册表的令牌的生成脚本将为注册表的令牌的生成/验证创 建私钥和根证书

                     ssl_cert:SSL证书的路径,仅当协议设置为 证书的路径,仅当协议设置为https时才应用

                     ssl_cert_key:SSL密钥的路径,仅当协议设置为 密钥的路径,仅当协议设置为https时才应

                     secretkey_path:用于在复制策略中加密或解密远程注册表的密码的密钥路径

 

       3、创建 、创建 https 证书以及配置相关目录权限

              openssl genrsa -des3 -out server.key 2048

              openssl req -new -key server.key -out server.csr

              cp server.key server.key.org

              openssl rsa -in server.key.org -out server.key

              openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

              mkdir  /data/cert

              chmod -R 777 /data/cert

 

       4、运行脚本进行安装

              ./install.sh

             

       5、访问测试

              https://reg.yourdomain.com的管理员门户(将reg.yourdomain.com更改为您的主机名harbor.cfg)。请注意,默认管理员用户名 密码为admin / Harbor12345

 

       6、上传镜像进行上传测试

              a、指定镜像仓库地址

                     vim /etc/docker/daemon.json

                     { "insecure-registries": ["serverip"] }

              b、下载测试镜像

                     docker  pull  hello-world

             

              c、给镜像重新打标签

                     docker tag serverip/hello-world:latest

             

              d、登录进行上传

                     docker login serverip

      

       7、其它Docker 客户端下载测试

              a、指定镜像仓库地址

                     vim /etc/docker/daemon.json

                     { "insecure-registries": ["serverip"] }

             

              b、下载测试镜像

                     docker pull  serverip/hello-world:latest

 

Docker管理工具

Docker Compose

       DockerFile只能是定义个容器,而Docker Compose可以定义多个。

Docker Machine

       简化了按照宿主机及操作系统特有的安装及配置步骤,及简化了安装Docker后才能运行Docker这一过程。

       提供了多平台多Docker主机的集中管理,使得应用由本地迁移到云端变得简单,只需要修改一下环境变量即可和任意Docker主机通信部署应用,可以使用一条命令就可以在公有云平台、私有云平台等地方创建及管理Docker主机。

 

Docker Swarm

       管理Docker集群的工作,可以单独部署一个节点,解决了Docker容器和宿主机的紧耦合、迁移、分组等问题。

       将一组Docker Engine作为一个集群进行管理,并提供了label、schedule、filter的能力,其中调度部分,允许用户定制主机的调度策略。

 

Docker Tutum

       提供容器管理云服务,使得用户可以方便的创建、启动、查看、关闭或部署容器,也提供了一个总览页面来方便用户在一处查看所有容器的状态。

 

Docker Shipyard

       基于Web的Docker管理工具,支持多主机,可以把多个Docker主机上的容器统一管理,可以查看镜像,build镜像,并提供RESTful API等。

 

Docker cAdvisor

       谷歌旗下的开源工具,监控图默认1秒刷新一次,显示最近一分钟的实时数据,不显示汇聚和历史数据,也没有阈值告警功能,此外无法同时监控多个Docker主机,不过由于简单、方便,而且具备很好的实时性能监控能力,所以适合特殊情况下的性能监控和问题排查。

 

 

Docker Compose

       Docker Compose是一个定义和管理多容器的工具,也是一种容器编排工具,前身是Pig,使用Python语言编写,使用Compose配置文件描述多个容器应用的架构,比如使用什么镜像、数据卷、网络、映射端口等,然后一条命令管理所有服务,如启动、停止、重启等。

       DockerFile只能定义一个容器,而DockerCompose可以定义多个。

       Docker Compose的ersion版本统一用3,3是兼容2的,version版本1已经废弃了;3和2最大的区别是3支持多机和单机,2仅支持单机;

       Docker Compose没有解决负载均衡的问题,因此需要借助其他工具实现服务发现和负载均衡。

       Docker Compose将管理的容器分为三层,工程(Project)、服务(Service)及容器(Container),一个工程中可以包含多个服务,每个服务中定义了容器运行的镜像、参数、依赖,一个服务当中可以包括多个容器实例。

 

安装

       #下载

curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose

      

#添加权限

       chmod +x /usr/local/bin/docker-compose

 

       #测试

       docker-compose --version

 

       # Pip工具安装

       pip install docker-compose

 

YAML文件

       Docker-Compose是使用.yml文件来编写的。

       YAML是一种标记语言,很直观的数据序列化格式,可读写高,类似于Xml数据描述语言,语法比Xml简单的多;YAML数据结构通过缩进来标识;连续的项目通过减号来标识;键值对用冒号分隔;数组用中括号;hash用花括号;

       不支持制表符Tab缩进,需要使用空格缩进;

       通常开头缩进2个空格;

       字符后缩进一个空格,如冒号、逗号、横杆

       用#进行注释、说明

       特殊字符用单引号引起来

       布尔值(true、false、yes、no、on、off)必须用引号括起来,这样分析器才会解释为字符串

 

常用命令

       #构建启动配置文件中指定的服务名容器,如果不加-f则默认为当前目录下的docker-compose.yml和docker0compose.override.yml文件

       docker-compose up -d 服务名

       docker-compose -f docker.yml up -d tomcat

 

       #创建或重新创建服务使用的镜像

       docker-compose build 配置的服务名称

      

       #进入容器

       docker-compose exec 服务名 base

 

       #删除所有容器、镜像

       docker-compose down

      

       #查看运行的容器

       docker-compose ps

      

       #重新启动容器

       docker-compose restart 服务名

 

       #在php-fom中不启动管理容器,并在容器执行 phpo -v 执行完成后删除容器

       docker-compose run -no-deps--rm php-fom php -v

 

       #构建镜像

       docker-compose build 服务名

 

       #不带缓存的构建

       docker-compose build --no-cache 服务名

 

       #查询服务的日志

       docker-compose logs 服务名

       docker-compose -f logs 服务名

 

       #验证配置文件,正确不输入,错误输出

       docker-compose config -q

 

       #以json的形式输出此服务的docker日志

       docker-compose events –json 服务名

 

       #暂时此服务容器

       docker-compose pause 服务名

 

       #恢复此服务容器

       docker-compose unpause 服务名

      

       #删除容器

       docker-compose rm 服务名

      

#停止容器

       docker-compose stop 服务名

      

#启动容器

       docker-compose start 服务名

 

常用配置文件参数

#services标签下的第二集标签是web,这个名词是用户自定义的服务名称,image则是指定服务的镜像名称或镜像id

services:

 web:

  image: hello-world

 

build构建镜像上下文路径,出了可以基于指定的镜像,还可以基于一份dockerfile,在使用up启动之时执行构建任务,这个构建标签就是build,可以指定dockerfile所在的文件夹路径dockerfile

image来自的镜像

args构建参数,在dockerfile中指定的参数可以在构建过程中指定环境变量,但是在构建成功之后取消,与EVN不同的是arg允许控制

       build:

               content: .

               args:

                - build=1

                - test

                  on: 第二种写法

 

       command覆盖容器启动后默认执行的命令,如cammand: [bunle,exec,thin,-I,3000]

       container_name自定义容器名称吗,如果自定义名称,则无法将服务scale到1容器之外

       deploy指定与部署和运行相关的配置,限版本3

       depends_on服务之间的依赖,控制服务启动顺序,正常是按顺序启动服务,如在没有启动数据库的情况下,先启动了应用,这时就会出现找不到数据库的问题,因此这个标签就解决了容器依赖、启动先后的问题。

       dns自定义DNS服务器,可以是单个值或列表

       entrypoinse覆盖entrypoint

       env_file从文件中添加环境变量,可以是单个值或列表,即可以单独定义一个存储变量的文件

       environment添加变量,可以是数字或字典,布尔值用括号括起来,会吧变量保存到镜像中,类似docker run -e指定容器的环境变量,而arg仅仅只能用在构建过程中

       expose容器服务端口

       links连接到另外一个容器,depends_on是解决启动顺序,而这个可以解决连接问题

              links:

               -db

               -db:databases

               -redis

       external_links连接Compose之外的容器

       extra_hosts添加主机名映射,与--add-host相同,往/etc/hosts文件中添加一些记录

       logging记录该服务的日志,与--log-driver相同,配置日志服务

       network_mode网络模式,与-net相同

       networks要加入的网络

              aliases 要加入网络时,为服务指定容器的静态ip地址

                     ipv4_address/ipv6_address

       pid将pid模式设置主机PID模式,与宿主机共享PID地址空间,pid:”host”,容器使用这个标签将能够访问和操作其他容器和宿主机的名称空间

       ports暴露端口,与-p相同,但端口不低于60

       sysctls在容器内设置内核参数,可以是数组或字典

       volumes挂载一个目录或一个已存在的数据卷容器到容器

       volumes_from从其他容器或服务挂载数据链,可选参数是:ro和:rw

       restart默认是no;当值为always时,容器总是重新启动;当值为no-failure时,即出现报错容器退出时,容器重新启动。

       hostname主机名称

       working_dir工作目录

 

部署Tomcat

version: ‘3.1’

services:

 tomcat:

  restart: always

  image: tomcat

  container_name: tomcat

  ports:

- 8080:8080

  volumes:

- ./webapps:/usr/local/tomcat/webapps

  environment:

   TZ: Asia/Shanghai

 

部署MySQL

version: ‘3.1’

 services:

  db:

   image: mysql

   restart: always

   environment:

- MYSQL_ROOT_PASSWORD: 12345

   command:

    --default-authentication-plugin=mysql_native_password

    --character-set-server=utf8mb4

    --collation-server=utf8mb4_general_ci

    --explicit_defaults_for_timestamp=true

    --lower_case_table_names=1

   ports:

- 12345:3306

   volumes:

    - ./data:/var/lib/mysql

 

 

Docker网络管理

       #查看docker网络连接

       docker network ls

 

Docker支持的五种网络模式

bridge(桥接模式):默认网络,Docker启动后会创建一个docker0网桥,默认创建的容器也是天价到这个网桥中,IP地址段是172.17.0.1/16

       docker run -it centos

       brctl show

       #查看network

       docker inspect 容器id

 

host(主机模式):容器不会获得一个独立的network namepace,而是与宿主机共用一个。

       docker run -it --network host centos

       docker inspect

 

none获取到独立的network namespace,但不为容器进行任何网络配置,这种类型的网络没有办法联网,封闭的网络能很好的宝座容器的安全性,可手动配置ip、子网掩码等信息

       docker run -it --network none

 

container与指定的容器使用同一个netwokr namespace,网卡配置也都是相同

 

自定义:默认和bridge网络模式一样

Docker网络访问流程

       先创建一个docker0的网桥,使用veth pair创建一对虚拟网卡,一端放到新创建的容器中,并重命名eth0,另一端放到宿主机上,以veth + 随机7个字符命名,并将这个网络设备加入到docker0网桥中,网桥自动为容器分配一个IP,并设置docker0的IP为容器默认网关。

       所以容器默认网络都加入了这个网桥,因此都可以彼此通信,同事在iptables添加SNAT转换网段IP,以便容器访问外网。

 

Docker网络访问原理

       Docker主要通过netfilter/iptbales实现网络通信。

       iptables由netfilter和iptables组成,netfilter组件是Liunx内核集成的信息包过滤系统,维护一个信息包过滤表,这个表用于控制信息包过滤处理的规则集,而iptables只是一个在用户空间的工具,用于增删改查这个过滤表的规则。

 

filter(过滤)

Input、Output、Forward

nat(地址转换)

Prerouting、Postrouting、Output

mangle(拆包、修改、封装)

Input、Output、Prerouting、Postrouting

raw(数据包状态跟踪)

Prerouting、Output

 

操作

       #容器访问外部

       iptables -t nat -nL

 

       #外部访问容器,MASQUERADE是动态获取宿主机外网IP

       iptables -t nat -A POSTROUTING -s 172.17.0.0/16 -j MASQUERADE

 

       docker run -itd -p 8080 centos

       iptables -t nat -nL

 

       #Networks可以查看到容器的IP地址

       docker inspect 容器id

 

       #在PREROUTING之前,将来自宿主机对外的IP:88的访问数据,通过tcp进行转发

       iptables -t nat -A PREROUTING -d 宿主机ip -p tcp(到容器协议) --dport 88(宿主机端口) -j DNAT --to 172.17.0.3:80

 

容器桥接到宿主机网络(物理网卡):

临时生效:

       ipconfig

       vi br.sh

       -------------------------------------

       #添加网桥

brctl addbr $br_name

#给网桥设置IP

ip addr add 宿主机ip/子网掩码数 dev $br_name

#删除已存在的eth0的网卡配置

ip addr del 宿主机ip/子网掩码数 dev eth0

#激活网桥

iplink set $br_name up

#添加eth0到网桥

brctl addif $br_name eth0

       -------------------------------------

 

       ./br.sh

       #查看是否有变化

       ifconfig

 

永久生效:

vi /etc/network/interfaces auto eth0 iface eth0 inet static

-------------------------------------

auto br0 iface br0 inet static address 192.168.1.120 netmask 255.255.255.0 gateway 192.168.1.1 dns-nameservers 192.168.1.1 bridge_ports eth0

       -------------------------------------

 

       vi /etc/default/docker

-------------------------------------

DOCKER_OPTS=”-b=br0”

-------------------------------------

      

       #重启docker

 

       ps -ef | grep docker

 

       docker run -it --network none centos

       docker ps

       docker attach 容器id

       ls

       ifconfig

       退出容器

       docker inspect 容器id

 

配置固定ip:

       vi ip.sh

-------------------------------------

C_ID=$(docker run -itd --net=none centos)

C_PID=$(docker inspect -f '{{.State.Pid}}' $C_ID)

# 创建network namespace目录并将容器的network namespace软连接到此目录,以便ip netns命令读取

mkdir -p /var/run/netns

ln -s /proc/$C_PID/ns/net /var/run/netns/$C_PID

# 添加虚拟网卡veth+容器PID,类型是veth pair,名称是vp+容器PID

ip link add veth$C_PID type veth peer name vp$C_PID

# 添加虚拟网卡到br0网桥

brctl addif br0 veth$C_PID

# 激活虚拟网卡

ip link set veth$C_PID up

# 设置容器网络信息

IP='ip地址/子网掩码数'

GW='网关'

# 给进程配置一个network namespace

ip link set vp$C_PID netns $C_PID

# 在容器进程里面设置网卡信息

ip netns exec $C_PID ip link set dev vp$C_PID name eth0

ip netns exec $C_PID ip link set eth0 up

ip netns exec $C_PID ip addr add $IP dev eth0

ip netns exec $C_PID ip route add default via 网关

-------------------------------------

      

       ./ip.sh

       ifconfig

 

       #重启docker

       docker inspect 容器id

       docker attach 容器id

       ifconfig

 

ip配置工具(pipework):

       git clone https://github.com/jpetazzo/pipework.git

cp pipework/pipework /usr/local/bin/

docker run -itd --net=none --name test01 centos

pipework br0 容器id ip地址/子网掩码@网关

yum install net-tools

ifconfig

 

容器SSH连接:

       docker run -it –name test centos

       yum install openssh-server

       passwd root

       docker commit test centos_ssh

       docker run -itd --network none --name test2 -p 2222:22 centos_ssh

       docker exec -it 容器id

       ./etc/init.d/sshd startr

 

发布了103 篇原创文章 · 获赞 34 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/Su_Levi_Wei/article/details/101072641