企业——Docker容器的搭建及简单应用


1.环境需求
不需要开虚拟机,只需要一个真机就行。
下载docker的安装包,可以在官网上下载  www.docker.com

   yum install -y pigz-2.3.4-1.el7.x86_64.rpm docker-ce-18.03.1.ce-1.el7.centos.x86_64.rpm container-selinux-2.21-1.el7.noarch.rpm     ##因为有依赖性,所以有时候需要把安装包全部下载 yum install -y *


2.docker的基础知识

(1)Docker与虚拟机比较:
   kvm 完全虚拟化,修改虚拟机,不对外部机有影响,完全和真机隔离   docker 操作系统的特殊进程,部分隔离.docker(s) 比 kvm(min) 要快,也比kvm小
   作为一种轻量级的虚拟化方式,Docker在运行应用上跟传统的虚拟机方式相比具有显著优势:
   -Docker容器很快,启动和停止可以在秒级实现,这相比传统的虚拟机方式要快得多。
   -Docker容器对系统资源需求很少,一台主机上可以同时运行数千个Docker容器。
   -Docker通过类似Git的操作来方便用户获取、分发和更新应用镜像,指令简明,学习成本较低。
   -Docker通过Dockerfile配置文件来支持灵活的自动化创建和部署机制,提高工作效率。

(2)docker的核心概念

   镜像(Image)
   -- 就是一个只读的模板。镜像是只读的,镜像中包含有需要运行的文件。例如:一个镜像可以包含一个完整的操作系统环境,里面仅安装了 Apache 或用户需要的其它应用程序。镜像可以用来创建 Docker 容器,一个镜像可以创建很多容器。Docker 提供了一个很简单的机制来创建镜像或者更新现有的镜像,用户甚至可以直接从其他人那里下载一个已经做好的镜像来直接使用。

   仓库(Repository)
   -- 是集中存放镜像文件的场所。有时候会把仓库和仓库注册服务器(Registry)混为一谈,并不严格区分。实际上,仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。仓库分为公开仓库(Public)和私有仓库(Private)两种形式。最大的公开仓库是 Docker Hub,存放了数量庞大的镜像供用户下载。国内的公开仓库包括 时速云 、网易云 等,可以提供大陆用户更稳定快速的访问。当然,用户也可以在本地网络内创建一个私有仓库。当用户创建了自己的镜像之后就可以使用 push 命令将它上传到公有或者私有仓库,这样下次在另外一台机器上使用这个镜像时候,只需要从仓库上 pull 下来就可以了。

   容器(container)
   -- Docker 利用容器(Container)来运行应用。容器是从镜像创建的运行实例。它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。容器的定义和镜像几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的。容器是Docker的运行组件,启动一个镜像就是一个容器,容器是一个隔离环境,多个容器之间不会相互影响,保证容器中的程序运行在一个相对安全的环境中。

  Docker镜像是由文件系统叠加而成。最底端是一个文件引导系统,即bootfs。Docker用户不会与引导文件系统有直接的交互。Docker镜像的第二层是root文件系统rootfs,通常是一种或多种操作系统,例如ubuntu等。在Docker中,文件系统永远都是只读的,在每次修改时,都是进行拷贝叠加从而形成最终的文件系统。Docker称这样的文件为镜像。一个镜像可以迭代在另一个镜像的顶部。位于下方的镜像称之为父镜像,最底层的镜像称之为基础镜像。最后,当从一个镜像启动容器时,Docker会在最顶层加载一个读写文件系统作为容器。Docker的这种机制我们称之为写时复制。

 

对docker的启动需要容器,需要镜像,仓库。
仓库(私有和公共)registry——>镜像images——>容器container——>提交之后——>保存到仓库registry里

 

(3)什么是Docker?

 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。Docker 属于 Linux 容器的一种封装,提供简单易用的容器使用接口。它是目前最流行的 Linux 容器解决方案。Docker 将应用程序与该程序的依赖,打包在一个文件里面。运行这个文件,就会生成一个虚拟容器。程序在这个虚拟容器里运行,就好像在真实的物理机上运行一样。有了 Docker,就不用担心环境问题。Docker容器的运行不需要额外的虚拟化管理程序(Virtual Machine Manager,VMM,以及Hypervisor)支持,它是内核级的虚拟化,可以实现更高的性能,同时对资源的额外需求很低。

 

(4)一个完整的Docker具有什么?

一个完整的Docker有以下几个部分组成:

  Docker Client  客户端

  Docker Daemon  守护进程

  Docker Image  镜像

  Docker Container  容器

 

Docker是CS架构,主要有两个概念:

  • Docker daemon: 运行在宿主机上,Docker守护进程,用户通过Docker client(Docker命令)与Docker daemon交互
  • Docker client: Docker 命令行工具,是用户使用Docker的主要方式,Docker client与Docker daemon通信并将结果返回给用户,Docker client也可以通过socket或者RESTful api访问远程的Docker daemon

      

 

 

3.docker对于game2048的部署
下载一个game2048.tar
还有所需要的镜像  rhel7
   docker load -i game2048.tar    ##导入game2048的镜像
   docker images     ##列出了所有顶层(top-level)镜像。查看宿主机上的镜像,Docker镜像保存在/var/lib/docker目录下。
   ip addr     ##在docker开启以后,会自动生成docker0的ip
   docker run -d --name vm1 game2048      ##生成一个vm1的容器  -d打入后台  利用game2048镜像
   docker ps      ##查看添加的容器
   docker inspect vm1     ##查看添加的容器vm1 会自动的给Docker分配ip,如下图:

      

   注意:docker inspect <container-id> or <image-id>:docker inspect命令会提取出容器或者镜像最顶层的元数据

   测试:在网页上输入 172.17.0.2  就会出来game2048的游戏界面
         

 

 

4.docker创建容器的命令
   导入镜像:
   docker load -i ubuntu.tar
   docker load -i rhel7.tar

   创建容器:
   docker run -d --name vm1 rhel7     ##创建vm1容器,利用rhel7的镜像
   docker run -it --name vm2 ubuntu      ## -it 具有交互界面
   docker run -it --name vm3 rhel7 bash     ##必须加bash才会出现交互界面

   注意:docker run <image-id>: docker run就是docker create和docker start两个命令的组合,支持参数也是一致的,如果指定容器名字时,容器已经存在会报错,可以增加 --rm 参数实现容器退出时自动删除。
  
   查看容器: docker ps    查看创建的全部的容器:docker ps -a

====================================================================================
   注意:虚拟机的ip是顺序分配的。刚开始的docker启动之后,会自动添加一个docker0:172.17.0.1,在之后创建的容器,会按照创建的顺序依次分配ip,比如:vm1的game2048的ip就是 172.17.0.2 ,到现在创建的vm2的ip就会分配为 172.17.0.3
====================================================================================


5.docker容器的交互界面的退出及容器(镜像)的删除
   (1)退出
   ctrl+P+Q    ##退出进程但是不停止,在ps的时候可以看到进程信息
   ctrl+D    ##直接退出,在ps的时候看不见正在运行的进程

   (2)删除
   <1>容器的删除
   docker rm vm1      ##有时容器正在运行,就会出现删除不了的情况 
   docker rm -f vm1     ##出现删除不了的情况时,需要 -f 强制删除
   docker container prune     ##将所有已经暂停的容器全部删除
   docker rm ‘docker ps -aq‘ 

   <2>镜像的删除
   docker rmi 镜像的名称


6.容器退出后的链接

   情况一:ctrl+P+Q 退出
   docker attach vm2
   ls
   touch file{1..20}
  
   情况二:ctrl+D 退出 这个直接将容器关闭了,而不是打入后台运行,所以 attach 连接不上
   docker attach vm2     ##会显示链接失败,vm2是一个停止运行的容器,所以需要先开启
   docker start vm2     ##应为是全部的关闭,所以需要先开启,在连接
   docker attach vm2
   ls      ##刚才建立的文件依旧存在

====================================================================================
   注意:一旦容器被删除,再创建一个名字一样的容器是没用的,容器内的建立的文件已经不存在了,如果需要保存的话,可以将容器commit保存一下
   docker commit <container-id>: 将容器的可读写层转换为一个只读层,这样就把一个容器转换成了不可变的镜像。
====================================================================================

   退出以后保存,转化成新的镜像:  

 docker commit  vm2  ubuntu:v1
   docker history ubuntu
   docker history ubuntu:v1
   可以看出两个镜像的不同,v1多了一层,就是新建的文件,保存下来了,这样用这个新的镜像,创建出来的容器都会含有新建的文件的这一层,如果不想要这一层文件,可以将 v1 这个镜像删除。

   转换成新的镜像之后:
   docker rm vm2
   docker run -it --name vm2 ubuntu:v1
   ls   ##文件层存在


7.docker的基础命令
   docker images   ##列出了所有顶层(top-level)镜像。
   docker load -i   ##导入镜像
   docker run --name   ##创建一个容器并运行
   docker ps   ##显示当前的并且正在运行的容器   
   docker ps -a   ##查看存在的但是没有运行的容器
   docker run -it(交互式) --name   ##交互式的,bash是用来交互的解释器
   docker rm   ##删除容器,但是在线情况下的容器不能删除,但是-f可以强制
              注意:镜像当中的是只读的,容器是在镜像的基础之上的写入自己独有的命令
   docker rmi   ##删除镜像
   docker history game2048:lastest   ##查看历史
   docker -d    ##打入后台
   docker inspect vm1  
   docker commit vm ubuntu:v1   ##提交,会生成新的镜像,并命名为v1
   docker configs   ##是用来的管理的
   docker container   ##是管理的子命令,和上层的一样,专门针对容器操作的
   docker cp /etc/passwd vm2:/tmp   ##物理机和容器之间复制文件
   docker exec  ##不需要登陆,在外部直接运行一些指令
   docker export   ##针对对象是容器,输出,转换成镜像文件,共享镜像
   docker logs   ##查看,记录在容器内执行的任何操作
   docker network   ##显示容器网络
   port  docker -p   ##端口映射   8080:80  物理机的:容器的
   docker top   ##显示容器内的进程


8.docker的exec的示例:

   如果不知道docker exec的用法,可以使用docker exec --help 来查看。

   docker cp /etc/passwd vm2:/tmp     ## 物理机和容器之间复制文件
   docker attach vm2
   ls
   cd /tmp
   ls    ##就可以看到cp进来的文件

   docker exec vm2 ls /passwd     ##直接就可以查看容器内的文件,不需要建立连接。
   docker exec vm2 rm /passwd     ##直接就可以删除容器内的文件   ,不需要建立连接。


9.docker的port的示例:
   docker run -d --name vm1 -p 8080:80 game2048
              ## -p 进行端口映射,真机的8080端口,映射到容器的80端口    Docker的端口映射是由 iptables 来实现的
   docker port vm1    ##用来查看端口映射
   测试:在网页上输入 172.25.254.9:8080   会出现game2048的游戏界面


10.使用官方的镜像加速器

  为什么要使用镜像加速器?我们使用Docker的第一步,应该是获取一个官方的镜像,例如mysql、wordpress,基于这些基础镜像我们可以开发自己个性化的应用。我们可以使用Docker命令行工具来下载官方镜像。但是因为网络原因,我们下载一个300M的镜像需要很长的时间,甚至下载失败。因为这个原因,阿里云容器Hub服务提供了官方的镜像站点加速官方镜像的下载速度


   在网页上:www.aliyun.com  登陆注册 —> 管理控制台 -> 镜像库 -> 镜像加速器

   cd /etc/docker/
   vim daemon.json
    {
       "registry-mirrors": ["https://vo5twm71.mirror.aliyuncs.com"]
    } 
   systemctl daemon-reload
   systemctl restart docker
   systemctl status docker


11.docker中的nginx的部署
   (1)导入镜像并创建新的容器vm1
   docker search nginx    ##在官方的仓库中下载相应需要寻找的镜像
   docker pull nginx    ##将找到的镜像拉取到本地的物理机上,物理机上的某一个特定的目录下面,docker的镜像的目录,可以访问的。
   docker run -d --name vm1 -p 8080:80 nginx  ##创建一个新的容器vm1和物理机的8080端口相映射。
   docker ps  ##命令查看创建的新的容器vm1  ps查看活跃的容器  ps -a查看全部的容器
      59b9de50f4b5        nginx               "nginx -g 'daemon of…"   3 seconds ago       Up 2 seconds        0.0.0.0:8080->80/tcp   vm1
   docker port vm1   ##查看vm1的端口的信息
      80/tcp -> 0.0.0.0:8080

   测试:在网页上输入 172.25.254.9:8080
 
   (2)nginx的发布页面的修改:
   方法一:可以在物理机上的某一个目录下,创建一个新的发布文件,发送到docker的默认的发布目录中
   cd /tmp  ##在物理机中
   mkdir docker
   cd docker/
   vim index.html
    server
   docker cp index.html vm1:/usr/share/nginx/html
  
   测试:在网页上输入 172.25.254.9:8080    ##注意要清除网页的缓存

   方法二:直接挂载,将物理机的目录挂载在docker容器的默认的发布目录下
   cd /tmp/docker
   mkdir web
   mv index.html web/
   docker rm vm1
   docker run -d --name vm1 -p 8080:80 -v /tmp/docker/web/:/usr/share/nginx/html nginx       ##将主机的目录/tmp/docker/web/作为容器的数据卷挂载到容器中,使宿主机和容器之间可以共享一个目录。以后就可以直接修改主机的目录,容器的发布目录也会跟着改变


12.数据卷管理

   数据卷(Data Volumes)是一个可供容器使用的特殊目录,它提供了很多有用的特性:对数据卷的修改会立马生效,数据卷会一直存在,直到没有容器使用,数据卷可以被多个容器使用,数据卷类似于Linux的mount。实质是在当前机器映射了一个目录到容器内部。

   数据卷容器(Data Volume Dontainers)其实就是一个普通的容器,只是我们专门用它提供数据卷供其它容器挂载使用。使用--volumes-from指定数据卷容器。多个--volumes-from将挂载多个数据卷容器。
   注意:使用--volumes-from参数所挂载的数据卷容器本身并不需要保持运行状态。如果删除了挂载的容器,数据卷并不会被自动删除,如果要删除一个数据卷,必需使用docker rm -v命令来指定同时删除管联的容器。

   docker run 在创建容器时使用 -v 参数可以挂载一个或多个数据卷到当前运行的容器中,-v的作用是将宿主机上的目录作为容器的数据卷挂载到容器中,使宿主机和容器之间可以共
享一个目录。

   (1)挂载数据卷到新创建的容器上:
    docker run -it --name vm1 -v /tmp/data1:/data1 -v /tmp/data2:/data2 rhel7 /bin/bash
    ##-v 参数可以重复使用,挂载多个数据卷到容器中,冒号前面的是宿主机的目录(本地目录不存在 docker 会自动创建),冒号后面的是容器中的挂载目录。docker commit 时卷的数据不会被保存。

   (2)默认挂载可以读写数据卷,也可以只读挂载:
   docker run -it --name westos2 -v /tmp/data2:/data2:ro rhel7 /bin/bash

   (3)挂载宿主机文件:
   docker run -it --name vm2 -v /etc/yum.repos.d/rhel-dvd.repo:/etc/yum.repos.d/rhel-dvd.repo:ro rhel7 /bin/bash

   (4)数据卷容器:
   docker create --name data -v /tmp/sharedata:/sharedata rhel7 /bin/true
   docker run -it --name vm1 --volumes-from data rhel7 /bin/bash
   docker run -it --name vm2 --volumes-from data rhel7 /bin/bash

   示例1:数据卷的挂载
   docker ps   ##删除没有用的容器
   docker run -it --name vm1 -v /tmp/docker/dvd.repo:/etc/yum.repos.d/dvd.repo:ro -v /tmp/docker/data1:/data1 -v /tmp/docker/data2:/data2 rhel7
    ##创建一个叫vm1的容器,将主机的dvd文件挂载到容器内的yum源的默认目录下,再挂载两个目录到容器内,ro代表只读挂载。
   bash-4.2# ls   ##会显示出挂载的文件或是目录
   bash-4.2# cd data1   ##进入到挂载的目录下,创建文件,文件是写入到主机的
   bash-4.2# touch file1
   bash-4.2# cd ..
   bash-4.2# cd data2   ##进入到挂载的目录下,创建文件,文件是写入到主机的
   bash-4.2# touch file2
   bash-4.2# cd /etc/yum.repos.d/   ##只读挂载了真机的yum源文件
   bash-4.2# ls
   bash-4.2# cat dvd.repo   ##只读挂载,因此可以 cat
   bash-4.2# rm -fr dvd.repo   ##但是,执行其他操作就会报错
    rm: cannot remove 'dvd.repo': Device or resource busy
   bash-4.2# yum repolist   ##因为挂载了yum源,所以可以下载
   bash-4.2# yum install -y httpd   ##下载是可以的
   bash-4.2# /usr/sbin/httpd   ##开启httpd服务
   bash-4.2# netstat -antlp   ##查看端口是否被开启
   bash-4.2# cd /var/www/html/
   bash-4.2# echo wf > index.html
  
   测试:在网页上输入 172.17.0.2  ##注意要清除网页的缓存

   示例2:数据卷容器的创建和使用
   docker create --name datavol -v /tmp/docker/dvd.repo:/etc/yum.repos.d/dvd.repo:ro -v /tmp/docker/data1:/data1 -v /tmp/docker/data2:/data2 rhel7 bash
   docker run -it --volumes-from datavol --name vm1 rhel7 bash
   docker run -it --volumes-from datavol --name vm2 rhel7 bash
   docker run -it --volumes-from datavol --name vm3 rhel7 bash
   注意:进入到容器内之后,容器内的数据是相同的


13.容器网络模型


   容器有四种网络模型:bridge 桥接模式、host 模式、container 模式和 none 模式

   ---桥接模式:该模式下 Docker Container 不具有一个公有 IP,即和宿主机的 eth0 不处于同一个网段。导致的结果是宿主机以外的世界不能直接和容器进行通信。
     桥接的实现步骤如下:
    (1) Docker Daemon 利用 veth pair 技术,在宿主机上创建两个虚拟网络接口设备,假设为veth0 和 veth1。而 veth pair 技术的特性可以保证无论哪一个 veth 接收到网络报文,都会将报文传输给另一方。
    (2) Docker Daemon 将 veth0 附加到 Docker Daemon 创建的 docker0 网桥上。保证宿主机的网络报文可以发往 veth0;
    (3) Docker Daemon 将 veth1 添加到 Docker Container 所属的 namespace 下,并被改名为 eth0。如此一来,保证宿主机的网络报文若发往 veth0,则立即会被 eth0 接收,实现宿主机到Docker Container 网络的联通性;同时,也保证 Docker Container 单独使用 eth0,实现容器网络环境的隔离性。

     示例:
   docker run -it --name vm1 ubuntu   ##默认的网络模型是桥接模式,这种模式下,自动按顺序分配ip


   ---host模式:容器和物理机共享一个网络,如何分辨访问的是容器还是物理机?开启的端口不一样,网络资源只有一份。
     host 模式是 bridge 桥接模式很好的补充。采用 host 模式的 Docker Container,可以直接使用宿主机的 IP 地址与外界进行通信,若宿主机的 eth0 是一个公有 IP,那么容器也拥有这个公有 IP。同时容器内服务的端口也可以使用宿主机的端口,无需额外进行 NAT 转换。当然,有这样的方便,肯定会损失部分其他的特性,最明显的是 Docker Container 网络环境隔离性的弱化,即容器不再拥有隔离、独立的网络栈。另外,使用 host 模式的 Docker Container 虽然可以让容器内部的服务和传统情况无差别、无改造的使用,但是由于网络隔离性的弱化,该容器会与宿主机共享竞争网络栈的使用;另外,容器内部将不再拥有所有的端口资源,原因是部分端口资源已经被宿主机本身的服务占用,还有部分端口已经用以 bridge 网络模式容器的端口映射。

     示例:
   docker run -it --name vm2 --net host ubuntu   ##设置网络模式为host型,因此ip addr看到的网络信息和主机的一样,都含有docker0


   ---自定义(container)模式:和定义的容器是网络共享的
     Container 网络模式:
    (1) 查找 other container(即需要被共享网络环境的容器)的网络 namespace;
    (2) 将新创建的 Docker Container(也是需要共享其他网络的容器)的 namespace,使用other container 的 namespace。
     Docker Container 的 other container 网络模式,可以用来更好的服务于容器间的通信。在这种模式下的 Docker Container 可以通过 localhost 来访问 namespace 下的其他容器,传输效率较高。虽然多个容器共享网络环境,但是多个容器形成的整体依然与宿主机以及其他容器形成网络隔离。另外,这种模式还节约了一定数量的网络资源。但是需要注意的是,它并没有改善容器与宿主机以外世界通信的情况

     示例:
   docker run -it --name vm3 --net container:vm1 ubuntu   ##设置网络模式为container型,vm1和vm3的ip 是一样的


   --none模式:网络环境为 none,即不为 Docker Container 任何的网络环境。一旦 Docker Container 采用了 none 网络模式,那么容器内部就只能使用 loopback 网络设备,不会再有其他的网络资源。可以说 none 模式为 Docker Container 做了极少的网络设定,但是俗话说得好“少即是多”,在没有网络配置的情况下,作为 Docker 开发者,才能在这基础做其他无限多可能的网络定制开发。在 none 网络模式下可以分配固定的 ip

     示例:  给容器添加固定的网络地址
   docker run -it --name vm4 --net none ubuntu   ##设置网络模式为none型,没有ip
   ip netns list   ##使用方法 ip netns  help   查看所有 network namespace
   docker inspect vm4 | grep Pid
   cd /proc/5065
   cd ns/
   ls
   pwd
   ln -s /proc/5065/ns/net /var/run/netns/5065
   ip link add name veth0 type veth peer name veth1
   ip addr   ##可以看到创建了一对虚拟网络接口设备
   ip link set up veth0
   ip link set up veth1   ##将两个接口设备开启
   ip addr   ##查看端口是否开启
   brctl addif docker0 veth0   ##将虚拟网络接口设备的一个与docker0链接
   ip netns list
   ip link set veth1 netns 5065   ##将虚拟网络接口设备的另一个与容器链接
   ip netns  exec 5065 ip link set veth1 name eht0
   ip netns exec 5065 ip addr add 172.17.0.100   ##给容器添加ip

   注意:docker attach vm4 -> ip add -> ip addr add 172.17.0.100/24 dev veth1   ##这样添加ip是不行的,不被允许的
  
   ip netns exec 5065 ip route add default via 172.17.0.1   ##添加网关


14.docker安全


   设置特权级运行的容器:--privileged=true   ##这个一开启就相当于是root用户

   docker run -it --name vm1 ubuntu
   root@63733880d3f0:/# ip addr
   root@63733880d3f0:/# ip addr del 172.17.0.2/16 dev eth0
    RTNETLINK answers: Operation not permitted

   上面的权限被限制了,是因为:
   docker inspect -f {{.HostConfig.Privileged}} vm1
    false     ##默认的权限是关闭的,也就是说,默认的是普通用户的身份
  
   因此,可以将这个设置为true,就运行了root用户的身份,就可以删除
   docker run -it --name vm2 --privileged=true ubuntu   ##创建用户的时候,开启权限
   root@a8dc66fa5137:/# ip addr
   root@a8dc66fa5137:/# ip addr del 172.17.0.2/16 dev eth0
   root@a8dc66fa5137:/# ip addr   ##成功删除


15.容器间互联:
   --link 参数可以在不映射端口的前提下为两个容器间建立安全连接, --link 参数可以连接一个或多个容器到将要创建的容器。
   --link 参数的格式为 --link name:alias,其中 name 是要链接的容器的名称,alias 是这个连接的别名。


16.Dockerfile的创建

=====================================================================================
   Dockerfile文件语法
(1)FROM(指定基础image)
   构建指令,必须指定且需要在Dockerfile其他指令的前面。后续的指令都依赖于该指令指定的image。FROM指令指定的基础image可以是官方远程仓库中的,也可以位于本地仓库。镜像可以指定标签。  格式:FROM <image>:<tag>

(2)RUN
   构建指令,RUN可以运行任何被基础image支持的命令。如基础image选择了ubuntu,那么软件管理部分只能使用ubuntu的命令。RUN指令可以有多条,每条RUN指令将在当前镜像基础上执行指定命令,并提交为新的镜像。当命令较长时,可以用\来换行。

(3)CMD(设置容器启动时执行的操作)
   设置指令,用于容器启动时指定的操作。该操作可以是执行自定义脚本,也可以是执行系统命令。该指令只能在文件中存在一次,如果有多个,则只执行最后一条。
   注意:
    1) CMD运行在镜像构建之后,容器启动的时候;
    2) CMD只执行最后一条
    3) CMD可以被用户指定的命令覆盖

(4)EXPOSE(指定容器需要映射到宿主机器的端口)
   设置指令,该指令会将容器中的端口映射成宿主机器中的某个端口。格式为:
   例如:
   EXPOSE 80 443 11211   ##告诉Docker服务端容器暴露的端口号,供互联系统使用。在启动容器时需要通过-P,Docker主机会自动分配一个端口转发到指定的端口;使用-p,则可以具体指定哪个本地端口映射过来。

(5)ENV(用于设置环境变量)
   构建指令,在image中设置一个环境变量。格式:
    ENV <key> <value>
   设置了后,后续的RUN命令都可以使用,容器启动后,可以通过docker inspect查看这个环境变量,也可以通过在docker run --env key=value时设置或修改环境变量。

(6)ADD(从src复制文件到容器的dest路径)
   构建指令,所有拷贝到容器中的文件和文件夹权限为0755,uid和gid为0。格式为:
    ADD <src> <dest>    ## <src> 是相对被构建的源目录的相对路径,可以是文件或目录的路径,也可以是一个远程的文件url;<dest>是容器中的绝对路径。该命令将复制指定的<src>到容器中的<dest>。其中<src>可以是Dockerfile所在目录的一个相对路径(文件或目录);也可以是一个URL;还可以是一个tar文件(自动解压为目录)。
# 如果是一个目录,那么会将该目录下的所有文件添加到容器中,不包括目录;如果文件是可识别的压缩格式,则docker会帮忙解压缩(注意压缩格式);如果<src>是文件且<dest>中不使用斜杠结束,则会将<dest>视为文件,<src>的内容会写入<dest>;如果<src>是文件且<dest>中使用斜杠结束,则会<src>文件拷贝到<dest>目录下。

(7)COPY
   格式为   COPY <src> <dest>
   复制本地主机的<src>(为Dockerfile所在目录的相对路径,文件或目录)为容器中的<dest>。目标路径不存在时,会自动创建。
   当使用本地目录为源目录时,推荐使用COPY。

(8)VOLUME(指定挂载点))
   设置指令,使容器中的一个目录具有持久化存储数据的功能,该目录可以被容器本身使用,也可以共享给其他容器使用。我们知道容器使用的是AUFS,这种文件系统不能持久化数据,当容器关闭后,所有的更改都会丢失。当容器中的应用有持久化数据的需求时可以在Dockerfile中使用该指令。格式: VOLUME ["<mountpoint>"]
   示例:
   FROM base 
   VOLUME ["/tmp/data"]
   运行通过该Dockerfile生成image的容器,/tmp/data目录中的数据在容器关闭后,里面的数据还存在。例如另一个容器也有持久化数据的需求,且想使用上面容器共享的/tmp/data目录,那么可以运行下面的命令启动一个容器:
   docker run -t -i -rm -volumes-from container1 image2 bash   ##container1为第一个容器的ID,image2为第二个容器运行image的名字。

(9)WORKDIR(切换目录)
   设置指令,可以多次切换(相当于cd命令),对RUN,CMD,ENTRYPOINT生效。格式:
   WORKDIR /path/to/workdir 

   示例:
   在 /p1/p2 下执行 vim a.txt 
   WORKDIR /p1
   WORKDIR p2
   RUN vim a.txt 
====================================================================================

(1)httpd的镜像的创建

   cd /tmp/docker
   vim Dockerfile
    FROM rhel7  ##基础镜像
    ENV HOSTNAME server1
    EXPOSE 80
    COPY dvd.repo /etc/yum.repos.d/dvd.repo  ##仓库没有yum源,将真机的yum源cp到容器里
    RUN rpmdb --rebuilddb && yum install -y httpd && yum clean all
    CMD ["/usr/sbin/httpd","-D","FOREGROUND"]
   docker build -t rhel7:v1 .   ##创建镜像 rhel7:v1
   docker images
   docker run -d --name vm1 rhel7:v1
   docker inspect vm1

   测试:在网页页面上输入:172.17.0.2

(2)nginx的原码编译的镜像的创建
   cd /tmp/docker
   vim Dockerfile
    FROM rhel7
    EXPOSE 80
    COPY dvd.repo /etc/yum.repos.d/dvd.repo
    ADD nginx-1.14.0.tar.gz /mnt
    RUN rpmdb --rebuilddb
    RUN yum install -y gcc pcre-devel make zlib-devel
    RUN yum clean all
WORKDIR /mnt/nginx-1.14.0
    RUN ./configure --prefix=/usr/local/nginx --with-threads --with-file-aio --with-http_stub_status_module
    RUN make
    RUN make install
    CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]
   docker build -t rhel7:v2 .
   docker run -d  --name vm2 rhel7:v2
   docker inspect vm2

   测试:在网页页面上输入:172.17.0.2   (会出现nginx的欢迎界面)

(3)nginx:v1的创建
   docker load -i distroless-java.tar
   docker images
   cd /tmp/docker
   vim Dockerfile
    FROM nginx:1.14.1 as base

    # https://en.wikipedia.org/wiki/List_of_tz_database_time_zones

    ARG Asia/Shanghai

    RUN mkdir -p /opt/var/cache/nginx && \
        cp -a --parents /usr/lib/nginx /opt && \
        cp -a --parents /usr/share/nginx /opt && \
        cp -a --parents /var/log/nginx /opt && \
        cp -aL --parents /var/run /opt && \
        cp -a --parents /etc/nginx /opt && \
        cp -a --parents /etc/passwd /opt && \
        cp -a --parents /etc/group /opt && \
        cp -a --parents /usr/sbin/nginx /opt && \
        cp -a --parents /lib/x86_64-linux-gnu/libpcre.so.* /opt && \
        cp -a --parents /lib/x86_64-linux-gnu/libz.so.* /opt && \
        cp -a --parents /lib/x86_64-linux-gnu/libc.so.* /opt && \
        cp -a --parents /lib/x86_64-linux-gnu/libdl.so.* /opt && \
        cp -a --parents /lib/x86_64-linux-gnu/libpthread.so.* /opt && \
        cp -a --parents /lib/x86_64-linux-gnu/libcrypt.so.* /opt && \
        cp -a --parents /usr/lib/x86_64-linux-gnu/libssl.so.* /opt && \
        cp -a --parents /usr/lib/x86_64-linux-gnu/libcrypto.so.* /opt && \
        cp /usr/share/zoneinfo/${TIME_ZONE:-ROC} /opt/etc/localtime

    FROM gcr.io/distroless/base

    COPY --from=base /opt /

    EXPOSE 80

    ENTRYPOINT ["nginx", "-g", "daemon off;"]


   docker build -t nginx:v1 .


17.缩减镜像空间
镜像每一层都有自己的ip,每一层都需要占用一定的空间
优化:--删除内部的缓存;尽量减少层数;
     --多级的RUN可以把多个RUN放在一层;
     --装了很多的包,安装完成后,并没有删除;
     --可以在一台真机上安装好,再另一个新的仓库里cp到新的仓库里;
     --基础镜像的缩减;


18.docker私有仓库的搭建

私有仓库的搭建:
   (1)下载镜像:docker search registry
   docker pull registry   ##或者本机上已经存在registry.tar包,使用docker load  -i registry.tar下载
   docker images   ##查看下载后的镜像
   (2)镜像更名:
   docker tag registry:2.3.1 registry:latest
   3运行docker容器:
   mkdir /tmp/docker/registry   ##创建数据存储的文件夹,将真机的/tmp/registry目录映射到/mnt/docker/registry
   docker run -d --name registry -p 5000:5000 -v /tmp/docker/registry:/var/lib/registry registry:2.3.1   ##启动容器,设定端口5000 ,然后映射文件夹,-v <宿主机目录>:<容器目录>
   (4)推送镜像到仓库:
   docker tag nginx localhost:5000/nginx
   (5)推送到本地的仓库上:
   docker push localhost:5000/nginx   ##此时可使用tree . 命令查看当前推送结构
   (6)开放注册https协议:
   vim /etc/docker/daemon.json
    "insecure-registries": ["172.25.254.9:5000"]
   (7)重启服务:systemctl restart docker
   (8)重启仓库:docker start registry   ##此时使用docker ps可以查看到仓库
   (9)更名:
   docker tag rhel7 172.25.254.9:5000/rhel7
   (10)推送到本地的仓库上:
   docker push 172.25.254.9:5000/rhel7
   (11)查看详细信息:
   docker inspect registry:2.3.1   ##可以看到他的主配置文件在/etc/docker/registry/config.yml

添加证书:
   (1)生成证书:
   openssl req \
   -newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key \
   -x509 -days 365 -out certs/domain.crt  ##注意主机名必须写成xx.xx的形式,同时在本机上要做好/etc/hosts的本地解析
   (2)删除刚才建好的仓库:
   docker rm -f registry
   (3)建立仓库:
   docker run -d --name registry -v `pwd`/certs:/certs -v /tmp/docker/registry:/var/lib/registry -e REGISTRY_HTTP_ADDR=0.0.0.0:443 -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key -p 443:443 registry:2.3.1   ##其中:-e REGISTRY_HTTP_ADDR=0.0.0.0:443 编辑容器内部参数   -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt 使用证书   -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key 私钥   -p 443:443 端口映射
   (4)添加认证:
   mkdir /etc/docker/certs.d
   mkdir /etc/docker/certs.d/westos.org
   cd /etc/docker/certs.d/westos.org
   cp /tmp/docker/certs/domain.crt ca.crt
   (5)更名:
   docker tag ubuntu:latest westos.org/ubuntu
   (6)推送到本地的仓库上:
   docker push westos.org/ubuntu

添加用户认证:
   (1)添加用户:
   docker run --rm --entrypoint htpasswd registry:2.3.1 -Bbn admin westos > auth/htpasswd
   追加用户:
   docker run --rm --entrypoint htpasswd registry:2.3.1 -Bbn wf westos >> auth/htpasswd
   (2)删除刚才建好的仓库:
   docker rm -f registry
   (3)建立仓库:
   docker run -d --name registry -v `pwd`/certs:/certs -v /tmp/docker/registry:/var/lib/registry -e REGISTRY_HTTP_ADDR=0.0.0.0:443 -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key -v `pwd`/auth:/auth -e REGISTRY_AUTH=htpasswd -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd -p 443:443 registry:2.3.1
   (4)更名:
   docker tag game2048:latest westos.org/
   (5)用户登陆:
    docker login westos.org   ##一定要先成功登陆以后才能推送
   (6)推送到本地的仓库上:
   docker push westos.org/game2048


19.docker-compose
   Docker Compose 是一个用来创建和运行多容器应用的工具。使用 Compose首先需要编写Compose 文件来描述多个容器服务以及之间的关联,然后通过命令根据配置启动所有的容器。Dockerfile 可以定义一个容器,而一个 Compose 的模板文件(YAML 格式)可以定义一个包含多个相互关联容器的应用。

   docker load -i haproxy.tar
   cp docker-compose-Linux-x86_64-1.22.0 /usr/local/bin/docker-compose
   chmod +x/usr/local/bin/docker-compose
   cd /tmp/docker/
   mkdir compose
   cd compose/
   vim docker-compose.yml
   mkdir haproxy
   cd haproxy/
   vim haproxy.cfg
   docker-compose up   ##可能会启动不了,报错显示,端口被占用
   systemctl stop httpd   ##可能是http服务占用了80端口,将服务关闭
   docker-compose up   ##再次开启就会起来

   重起一个shell:
   docker ps   ##就可以看到compose运行
   cd /tmp/docker/web
   vim index.html
    wf
   docker cp index.html compose_web1_1:/usr/share/html
   vim index.html
        westos
   docker cp index.html compose_web2_1:/usr/share/html

   测试: 在网页上就可以看到负载均衡的结果

   注意:如果要开启/关闭 compose ,必须要在compose的目录下,因为它会要读取yml文件,不在目录下开启/关闭,会发生报错


 

转载于:https://www.cnblogs.com/wf-aiyouwei/p/10003930.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/484717.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第一章 计算机网络 3 标准化工作和相关组织 [计算机网络笔记] -简单浏览了解即可

第一章 计算机网络 3 标准化工作和相关组织 本笔记参考书目&#xff1a; 计算机网络&#xff08;第8版&#xff09;谢希仁2021王道计算机网络视频公开课 本节重点&#xff1a; 标准化工作和相关组织 转载请注明文章来源&#xff01; 标准化分类 标准化流程 标准化相关组织 …

张亚勤、韦乐平等综述论文:通信人工智能的下一个十年

来源&#xff1a;专知【摘 要】移动通信技术走过了37年的发展历程&#xff0c;人工智能技术也已走过了64年的发展历程。从早期的各自独立演进&#xff0c;到5G与人工智能开始深度融合发展&#xff0c;“5G与人工智能”已被业界视为一组最新的通用目的技术组合&#xff0c;对垂…

Juventas, the Roman Goddess of Youth [ Juventas, 罗马青春女神]

Juventas, the Roman Goddess of Youth &#x1f478; Juventas, 罗马青春女神——尤文图斯 Introduction Juventas was a minor Roman goddess whose attributes were regarded by the Romans as applying particularly to the imperishable vigour and immortal glory of t…

Hinton的GLOM模型与千脑理论有何本质不同?

来源&#xff1a;AI科技评论编译 &#xff1a;琰琰校对 &#xff1a;青暮Geoffrey Hinton在最新发表的一篇论文“如何在神经网络中表示部分-整体层次结构”中提出了一种被称为GLOM的新理论。关于GLOM模型与千脑理论&#xff08; Thousand Brains Theory &#xff09;之间有何差…

ThinkPHP3(添加,修改,删除)

实现商品的添加 1、在add.html页面中更改表单元素的名称 Goods控制器的add&#xff08;&#xff09;方法中获取商品分类 在add.html中循环获取 2、设置提交的位置 3、添加商品代码参见GoodsController.class.php 方法一&#xff1a; $this->redirect();也是跳转 方法二(用cr…

第二章 数据的表示和运算 2.1.1 进位计数制 [计算机组成原理笔记]

第二章 数据的表示和运算 2.1.1 进位计数制 本笔记参考书目&#xff1a; 计算机组成原理&#xff08;第六版.立体化教材&#xff09;白中英、戴志涛2021王道计算机组成原理视频公开课 本节重点&#xff1a; 二进制 <-> 八进制/十六进制十进制 -> 二进制 转载请注明…

重磅!脑机接口突破登Nature封面,脑中“笔迹”转屏幕文字破纪录,准确率超99%...

来源&#xff1a; 物联网之家研究团队将人工智能软件与一款脑机接口设备结合起来&#xff0c;与一名大脑中植入脑机接口设备的瘫痪患者合作&#xff0c;让该患者想象他拿着一支笔&#xff0c;在一张横线纸上“尝试”写字&#xff0c;就像他的手没有瘫痪一样。并将该男子手写意图…

python D28 粘包

一、两种粘包&#xff1a; MTU简单解释&#xff1a; MTU是Maximum Transmission Unit的缩写。意思是网络上传送的最大数据包。MTU的单位是字节。 大部分网络设备的MTU都是1500个字节&#xff0c;也就是1500B。如果本机一次需要发送的数据比网关的MTU大&#xff0c;大的数据包就…

第二章 数据的表示和运算 2.1.2 BCD码 [计算机组成原理笔记]

第二章 数据的表示和运算 2.1.2 BCD码 本笔记参考书目&#xff1a; 计算机组成原理&#xff08;第六版.立体化教材&#xff09;白中英、戴志涛2021王道计算机组成原理视频公开课 本节重点&#xff1a; 8421/2421/余3码 转载请注明文章来源&#xff01; BCD码 BCD&#xff…

世界因数学而改变

来源&#xff1a;数学中国1971年尼加拉瓜发行了十张一套题为“改变世界面貌的十个数学公式”邮票&#xff0c;由一些著名数学家选出十个以世界发展极有影响的公式来表彰。其实不难发现选出的“数学公式”很多都是物理学中的公式&#xff0c;当然正是因为有强大的数学&#xff0…

第一章 计算机网络 4 性能指标 [计算机网络笔记]

第一章 计算机网络 4 性能指标 本笔记参考书目&#xff1a; 计算机网络&#xff08;第8版&#xff09;谢希仁2021王道计算机网络视频公开课 本节重点&#xff1a; 数据率/带宽/吞吐量时延/时延带宽积/RTT/利用率 转载请注明文章来源&#xff01; 速率/数据率 速率&#xf…

数字孪生卫星:概念、关键技术及应用

来源&#xff1a;问空天作者&#xff1a;刘蔚然&#xff0c;陶 飞&#xff0c;程江峰&#xff0c;张连超&#xff0c;易旺民摘 要&#xff1a;在分析卫星产业发展趋势与升级转型新需求后&#xff0c;为推动卫星与新技术融合发展&#xff0c;提升大型卫星工程的整体管理水平与流…

第一章 计算机网络 5 分层结构/协议/接口/服务的概念 [计算机网络笔记]

第一章 计算机网络 5 分层结构/协议/接口/服务的概念 本笔记参考书目&#xff1a; 计算机网络&#xff08;第8版&#xff09;谢希仁2021王道计算机网络视频公开课 本节重点&#xff1a; 分层结构/协议/接口/服务实体/对等实体PCI/SDU/PDU 转载请注明文章来源&#xff01; 分…

机器学习2021 | 机器学习算法如何商业落地?

来源&#xff1a;传感器技术未来十年最火的科技发展方向之一&#xff0c;那就是AI技术&#xff0c;而使其得到迅猛发展的就是机器学习了。机器学习&#xff0c;顾名思义&#xff0c;就是人类定义一定的计算机算法&#xff0c;让计算机根据样本和人为干预&#xff0c;进行归纳和…

运行期优化

前言 在部分的商用虚拟机中&#xff0c;Java程序最初是通过解释器进行解释执行的&#xff0c;当虚拟机发现某个方法或代码块运行特别频繁的时候&#xff0c;就会把这些代码认定为“热点代码”。为了提高热点代码的执行效率&#xff0c;在运行时&#xff0c;虚拟机将会把这些代码…

第一章 计算机网络 6 OSI参考模型 [计算机网络笔记]

第一章 计算机网络 6 OSI参考模型 本笔记参考书目&#xff1a; 计算机网络&#xff08;第8版&#xff09;谢希仁2021王道计算机网络视频公开课 本节重点&#xff1a; OSI参考模型的7层次结构及其功能OSI参考模型数据传输的过程 转载请注明文章来源&#xff01; 计算机网络的…

第二章 数据的表示和运算 2.1.3 字符与字符串 [计算机组成原理笔记]

第二章 数据的表示和运算 2.1.3 字符与字符串 本笔记参考书目&#xff1a; 计算机组成原理&#xff08;第六版.立体化教材&#xff09;白中英、戴志涛2021王道计算机组成原理视频公开课 本节重点&#xff1a; ASCII码/汉字编码字符串在内存中的表示 转载请注明文章来源&…

评阅百篇博士论文后我发现:博士生发SCI越多,通常科研能力越差!

来源&#xff1a;秦四清科学网博客 作者&#xff1a;秦四清多年来&#xff0c;我评阅了上百部博士学位论文&#xff0c;也参加了上百次的博士学位论文答辩会&#xff0c;我和不少老师有一个共同的深刻感受&#xff1a;在攻读博士期间&#xff0c;发表了多篇sci论文的博士生&…

深入分析5nm芯片

来源&#xff1a; 半导体行业观察苹果公司于2020年10月发布了新型智能手机“iPhone 12”系列&#xff0c;搭载的是采用5纳米工艺的全球首个名为“A14 BIONIC”芯片。苹果公司将“A14 BIONIC”芯片应用到了iPhone 12、新款“iPad Air”。2020年11月苹果公司又发布了搭载“Apple …

第二章 数据的表示和运算 2.1.5 汉明(海明)校验码 [计算机组成原理笔记]

第二章 数据的表示和运算 2.1.5 汉明(海明)校验码 本笔记参考书目&#xff1a; 计算机组成原理&#xff08;第六版.立体化教材&#xff09;白中英、戴志涛2021王道计算机组成原理视频公开课 本节重点&#xff1a; 海明&#xff08;Hamming&#xff09;校验码原理和编码方法 …