Docker(二)

Docker(二)

上一篇简单认识了Docker,并且基于已有的镜像运行了容器。

Docker构建镜像

既然有官方提供的镜像,那么自己也可以进行docker镜像的制作。

DockerFile

  • DockerFile是一个包含用于组合镜像的命令的文本文档
  • Docker通过读取DockerFile中的指令按步自动生成镜像
  • docker build -t 机构/镜像名 <:tags> DockerFile目录 对dockerFile进行解析生成镜像

DockerFIle常用命令

  • FROM tomcat:lastest 设置基准镜像
  • MAINTAINER echi.com 维护人
  • WORKDIR /usr/local/tomcat/webapps 切换工作目录
  • ADD docker-web ./docker-web 将制定的文件或目录复制到镜像的指定目录下

构建一个自己的镜像

首先创建一个工作目录

mkdir /usr/images/firstDockerFile

在工作目录中创建要放入tomcat中的项目

mkdir docker-web

echo “

my first docker file index

>” > docker-web/index.html

创建Dockerfile

vi Dockerfile

FROM tomcat:latest

MAINTAINER echi

#因为是基于tomcat的项目,所以默认工作路径定在webapps下

WORKDIR /usr/local/tomcat/webapps

#将docker-web整个复制到工作目录下

ADD docker-web ./docker-web

完成Dockerfile和项目后,开始构建镜像。

docker image -t echi/mywebapp:1.0 .

因为命令是直接在/usr/images/firstDockerFile下执行的,所以可以用.来代替路径。 此处也可以用绝对路径。

命令执行完成后,使用docker images就可以看到构建成功的镜像了。

镜像分层概念(layer)

首先谈谈分层概念, 镜像和容器的分层比较好理解,镜像就类似于系统光盘,是只读的,容器就类似于使用光盘装好的系统,可读可写。

在镜像内部也有分层的概念。

在上一步构建镜像的时候就有体现,在docker build的时候,会显示出一些步骤。

在每一步之后都会显示出一个容器id, 这是docker产生的临时容器。

docker镜像构建的时候,每一步都会产生一个临时容器,快照性质的容器,也是一个存档。

这个设计的优势在于, 如果我们想要部署的是docker-web02这个项目,那么前几步的构建就是已经做过的,所有不需要重新处理。

所以只需要在第三步的基础上再进行一次第四步即可。这样就有效的节省了系统资源。

Dockerfile基础命令

FROM - 基于基准镜像

  • FROM centos 制作基准镜像(基于centos:latest)
  • FROM scratch 不依赖任何肌醇镜像base image
  • FROM tomcat
  • 尽量使用官方提供的BaseImage

LABLE & MAINTAINER - 说明信息

  • MAINTAINER 维护人或维护机构信息
  • LABLE version = “1.0”
  • LABLE description = “echi1995.com first docker image”

lable并不会产生作用,只是放在文件中的描述信息

WORKDIR - 设置工作目录

  • WORKDIR /usr/local
  • WORKDIR /usr/local/newdir 自动创建不存在的目录
  • 尽量使用绝对路径

ADD & COPY - 复制文件

  • ADD hello / 复制到根路径
  • ADD test.tar.gz / 添加根目录并解压
  • ADD 除了复制,还具备添加远程文件功能

ENV - 设置环境常量

  • ENV JAVA_HOME /usr/local/openjdk8
  • RUN ${JAVA_HOME}/bin/java -jar test.jar
  • 尽量使用环境常量,可提高程序维护性

Dockerfile运行指令

  • RUN : 在Build构建时执行命令
  • ENTRYPOINT : 容器启动时执行的命令
  • CMD: 容器启动后执行默认的命令或参数

RUN - 构建时运行

  • RUN yum install -y vim : Shell命令格式
  • RUN [“yum”, “install”, “-y”, “vim”] : Exec命令格式

为什么要有两种命令格式呢?

使用Shell执行时,当前shell是父进程,生成一个子shell进程。

在子shell中执行脚本,脚本执行完毕,退出子shell,回到当前shell。

如果使用Exec方式,会用Exec进程替换当前进程,并且保持PID不变。

执行完毕直接退出,并不会退回之前的进程环境。

ENTRYPOINT启动命令

  • ENTRYPOINT(入口点)用于在容器启动时执行命令
  • Dockerfile中只有最后一个ENTRYPOINT会被执行
  • ENTRYPOINT[“ps”] 推荐使用Exec格式

CMD默认命令

  • CMD用于设置默认执行的命令
  • 如Dockerfile中出现多个CMD,则只有最后一个被执行
  • 如容器启动时附加指令,则CMD被忽略
  • CMD[“ps”, “-ef”] 推荐使用Exec格式

容器间Link单向通信

在前面都是单个容器内部进行操作,但是有时候往往需要容器之间进行通信。

在每个Docker环境中,启动的容器都会分配一个虚拟ip。 这个ip无法访问,只是在docker内部彼此通信的标识。

当两个容器被创建后天然会拥有自己的虚拟ip,而且在docker内部这两个虚拟ip之间是彼此互联的。

但是如果容器之间使用虚拟ip进行通信是有问题的, 因为在docker中创建容器非常容易,每创建一个容器都会新分配一个ip地址。

比如随着时间推移,MySQL容器 172.17.0.24不再使用,而是换成了172.17.0.28,但是24是已经配置在tomcat中。这时只能通过修改tomcat容器中的配置文件来重新指向新的MySQL容器。

这样如果容器数量少则还好,如果部署数量过多,上百个tomcat容器指向一个MySQL容器,如果此时发生改变,要修改的花费是不可接受的。

因此可以给容器起个名字,连接的时候不要再直接去连接虚拟ip,而是通过名称去连接,这样docker就可以自动的根据名称连接到对应的容器上。

#给容器起个名称

docker run -d –name web tomcat

#这样就给tomcat这个容器起了个名字叫web

docker run -d –name database mysql

#查看docker容器的ip

docker inspect 容器id

#在输出的一大串信息中,找到NetworkSettings这一项,其中的IPAddress就是docker容器的虚拟ip

#如果此时我们进入tomcat容器,去pingMySQL容器的虚拟ip是可以ping的通,但是ping database是不通的,因为还没有关联

#要关联很简单,移除tomcat容器,在创建的时候加上一个参数即可

docker run -d –name web –link database tomcat

#这样就添加上database的名称到tomcat中,在tomcat容器中也可以使用databaseping的通MySQL

容器间Bridge网桥双向通信

所谓网桥就是一个虚拟的网络桥接,是docker环境与外界通信必不可少的组件。但是这个网桥组件是完全虚拟出来的一个组件,网桥的主要用途就是让docker容器与外界进行通信,网桥把容器发出的数据包通过网桥传输给外部的物理网卡,通过物理网卡与外部的网络进行通信。

网桥还可以对容器从网络层面进行分组,将一组容器绑定在同一个网桥上,那么这几个容器就可以进行互联互通。

#列出docker网络信息

docker network ls

#在输出中可以看到有一个bridge,这是默认网桥

docker network create -d bridge my-bridge

#再次查看,可以看到新出现了一个叫做my-bridge的网桥。上句中 bridge是标识创建的是网桥。

#将web绑定到新创建的网桥上

#绑定在同一个网桥上的容器可以进行通信

docker network connect my-bridge web

网桥实现原理

当创建一个网桥,docker就会在linux内部创建一个虚拟网卡,这个虚拟网卡也承担了网关的作用。

但是虚拟网卡毕竟是虚拟出来的,与外界通信的时候仍需要通过物理网卡转换,再通过物理网卡接受返回的数据包。

Volume容器间共享数据

当容器间需要进行数据共享的时候,比如部署了多个tomcat容器,提供相同的功能。那么可能会有一些静态资源需要存放在容器中。

如果每个容器都维护自己的静态文件,那么当静态文件需要改动的时候只能一个一个去改。

因此可以通过共享数据的方式,使多个容器之间共享相同的文件。

通过设置-v挂在宿主机目录

  • docker run –name 容器名 -v 物理机路径:容器内挂在路径 镜像名

通过–volumes-from共享容器内挂载点

  • 创建共享容器
  • docker create –name 挂载点名字-v 物理机路径:容器内挂在路径 镜像名/bin/true #创建挂载点
  • docker run –name 容器名 –volumes-from 挂载点名字 镜像名 # 使用挂载点

两种方法其实都是一样的,只是通过–volumes-from创建的挂载点不用重复输入路径。

DockerCompose

多容器部署问题

如果需要部署docker环境,可能会需要多个docker容器协同工作,比如通过nginx负载均衡,通过tomcat处理请求,通过mysql持久化数据。那么如果上线的时候就需要启动多个docker,需要很多命令才能发布,那有没有什么方法可以简化这个操作呢?

DockerCompose可以通过脚本开安装这些容器,同时配置好容器间的关系和容器需要的配置文件。

DockerCompose介绍

  • Docker Compose单机多容器部署工具
  • 通过yml文件定义多容器如何部署
  • WIN/MAC 默认提供DOcker Compose,Linux需安装

docker compose官网

安装Docker Compose

直接进入docker compose中,打开install页面。

https://docs.docker.com/compose/install/

下载docker compose

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

给docker compose授权

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

QuickStart 使用DockerCompose搭建WordPress

https://docs.docker.com/compose/wordpress/

  • 根据文档,首先创建一个目录,并创建docker-compose.yml文件。

  • 并将文档中的内容粘贴到docker-compose.yml中

  • 使用docker-compose up -d构建项目

  • 如果要关闭,则可以使用docker-compose down


   转载规则


《Docker(二)》 echi1995 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
2020.8-9月 面试整理(Java基础篇) 2020.8-9月 面试整理(Java基础篇)
最近很久没有更新博客,在8-9月这个节骨眼上大量的面试。 最近的学习重心放在了算法上,力扣上的题也差不多做了三百道,周赛也是期期不落。 最近刚入职新公司,还在熟悉环境,就先整理一下这一个月左右的面试题吧。 一个来月的面试也从刚开始的投简历也
下一篇 
Docker(一) Docker(一)
Docker(一)Docker是一个容器技术,容器不仅仅只有Docker,但Docker一定是使用人数最多的容器技术。 和Docker一样属于容器技术的还有Kubernetes,因为其单词太长,也被简称为k8s。 Docker的发展史Doc
  目录