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中,打开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