Docker镜像是应用发布的标准格式。可支撑一个Docker容器的运行
Dockerfile创建镜像并在容器中运行。
Dockerfile是由一组指令组成的文件,其中每条指令对应Linux中的一条命令,Docker程序将读取Dockerfile中的的指令生成指定镜像使用
1)结构组成(四部分)
Dockerfile操作指令
在编写Dockerfile时,有严格的格式需要遵循:第一行必须使用FROM指令指明所基于的镜像名称;之后使用MAINTAINER指令说明维护该镜像的用户信息;然后是镜像操作相关指令,如RUN指令,每运行一条指令,都会给基础镜像添加新的一层;最后使用CMD指令,来指定启动容器时要运行的命令操作。
常见的指令表如下:
指令 | 含义 |
---|---|
FROM镜像 | 指定新镜像所基于的镜像,第一条指令必须为FROM指令, 每创建一个镜像就需要一条FROM指令。 |
MAINTAINER名字 | 说明新镜像的维护人信息 |
RUN命令 | 在所基于的镜像上执行命令,并提交到新的镜像中 |
CMD [ “要运行的程序”,”参数1, “参数2”] | 指令启动容器时要运行的命令或者脚本,Dockerfile只能有一条CMD命令,如果指定多条则只能最后一条被执行 |
EXPOSE 端口号 | 指定新镜像加载到Docker时要开启的端口 |
ENV 环境变量 变量值 | 设置一个环境变量的值,会被后面的RUN使用 |
ADD 源文件/目录 目标文件/目录 | 将源文件复制到目标文件,源文件要与Dockerfile位于相同目录中,或者是一个URL |
COPY 源文件/目录 目标文件/目录 | 将本地主机上的文件/目录复制到目标地点,源文件/目录要 与Dockerfile在相同的目录中 |
VOLUME[“目录"] | 在容器中创建一个挂载点 |
USER 用户名/UID | 指定运行容器时的用户 |
WORKDIR 路径 | 为后续的RUN、CMD、ENTRYPOINT指定工作目录 |
ONBUILD 命令 | 指定所生成的镜像作为一个基础镜像时所要运行的命令 |
HEALTHCHECK | 健康检查 |
3) 示例
首先需要创建目录,作为生成镜像的工作目录,然后分别创建并编写Dockerfile文件、需要运行的脚本文件以及要复制到容器的文件
① 创建工作目录
[root@localhost~]# mkdir apache
[root@localhost~]# cd apache
② 创建并编写Dockerfile文件
[root@localhost apache]# vim Dockerfile
#基础镜像
FROM centos:7
#用户信息
MAINTAINER test
#基于基础镜像安装软件
RUN yum -y update
RUN yum install -y httpd
#开启端口
EXPOSE 80
#复制首页到指定站点
ADD index.html /var/www/html/index.html
#复制启动脚本到镜像中
ADD run.sh /run.sh
#设置 run.sh执行权限
RUN chmod 755 /run.sh
#启动容器时执行脚本
CMD ["/run.sh"]
③ 编写执行脚本内容
[root@localhost apache]# vim run.sh
#!/bin/bash
rm -rf /run/httpd/* #清理httpd的缓存
exec /usr/sbin/apachectl -D FOREGROUND #启动apache服务
④ 创建web测试首页
[root@localhost apache]# echo "test web" > index.html
#创建的三个文件都在/apache目录中
#目前容器及镜像都没有
⑤ 使用Dockerfile生成镜像
编写完成Dockerfile以及相关内容之后,可以通过docker build命令来创建镜像。
命令格式:
docker build [选项] 路径
常用选项:
#使用Dockerfile自动生成镜像
[root@localhost apache]# docker build -t httpd:centos .
Sending build context to Docker daemon 4.096kB
Step 1/9 : FROM centos:7
7: Pulling from library/centos
ab5ef0e58194: Pull complete
Digest: sha256:4a701376d03f6b39b8c2a8f4a8e499441b0d567f9ab9d58e4991de4472fb813c
Status: Downloaded newer image for centos:7
---> 5e35e350aded
Step 2/9 : MAINTAINER test
---> Running in 671d3fa20a48
Removing intermediate container 671d3fa20a48
………………省略内容
Step 9/9 : CMD ["/run.sh"]
---> Running in 16cc2e1b490e
Removing intermediate container 16cc2e1b490e
---> 4fd096d992ec
Successfully built 4fd096d992ec
Successfully tagged httpd:centos
整个创建过程中,每运行一次Dockerfile中的指令,都会给初始镜像加上新的一层(docker是分层的,每一层run执行都会产生一个临时容器,执行完成后就会被remove掉)
⑥ 使用新的镜像运行容器
#将新生成的镜像加载到容器中运行
[root@localhost apache]# docker run -d --name web1 -p 12345:80 httpd:centos
基于已有镜像创建主要使用docker commit命令。实质就是把一个容器里面运行的程序以及该程序的运行环境打包起来生成新的镜像
命令格式:
docker commit [选项] 已有容器ID/名称 仓库名称:标签
常用选项:
① 创建并查看已有容器,需要记住容器ID
② 使用docker commit命令创建镜像
[root@localhost ~]# docker commit -m "new” -a ''daoke" 9e22619aa48d daoke:test
[root@localhost ~]# docker images
创建完成后,会返回新创建镜像的ID信息。查看本地镜像列表可以看到新创建的镜像信息
通过导入操作系统模板文件可以生成镜像,模板可以从OPENVZ开源项目下载,下载地址为:http://openvz.org/Download/template/precreated
① 下载模板
这里我是已经有这个包了,直接使用
使用wget下载
wget http://download.openvz.org/template/precreated/debian-7.0-x86-minimal.tar.gz
② 使用docker的导入命令将下载的模板压缩包导入为本地镜像
[root@localhost ~]# cat debian-7.0-x86-minimal.tar.gz | docker import - daoke:debian
③ 导入完成后会返回生成镜像的ID。查看本地镜像列表可以看到新创建的镜像信息
[root@localhost ~]# docker images
随着创建的镜像日益增多,就需要有一个保存镜像的地方,就是仓库。目前有两种仓库:公有仓库和私有仓库。最方便的就是使用公有仓库上传和下载镜像,下载公有仓库中的镜像不需要注册,但是上传镜像到公有仓库是需要注册的。公有仓库网址:https://hub.docker.com,填写完成仓库的ID号、邮箱以及登录仓库的密码并在邮箱中进行激活就可以上传自己的镜像。
这里我们来构建一个简单的本地私有仓库registry(没有图形化界面)
① 下载 registry仓库镜像
[root@localhost ~]# docker pull registry
② 客户终端配置加速
#不配置加速在上传镜像时会报错
[root@localhost ~]# vim /etc/docker/daemon.json
{
"insecure-registries":["192.168.11.141:5000"], #指明仓库节点IP以及端口
"registry-mirrors": ["https://7rp8a2t8.mirror.aliyuncs.com"]
}
[root@localhost ~]# systemctl restart docker #改过配置,需要重启
③ 创建registry容器并挂载
#在本地启动一个私有仓库服务,监听端口号为5000
#宿主机的/data/registry自动创建挂载容器中的/tmp/registry
创建容器时-v挂载 宿主机上的/data/registry提供给容器中的/tmp/registry使用。
-v指定外部路径是会自动创建的,不需要自己去mkdir手动创建
[root@localhost ~]# docker run -d -p 5000:5000 -v /data/registry:/tmp/registry registry
④ 更改标签为192.168.11.141:5000/nginx(docker tag 原镜像名 仓库IP:端口/镜像名)
[root@localhost ~]# docker pull nginx
[root@localhost ~]# docker images
[root@localhost ~]# docker tag nginx:latest 192.168.11.141:5000/nginx
⑤ 上传镜像至私有仓库(docker push 仓库IP:端口/镜像名)
[root@localhost ~]# docker push 192.168.11.141:5000/nginx
⑥ 获取私有仓库列表
[root@localhost ~]# curl -XGET http://192.168.11.141:5000/v2/_catalog
#显示上传成功
{“repositories”:[“nginx”]}
⑦ 测试私有仓库下载
可以另外打开节点测试下载
[root@localhost ~]# docker pull 192.168.11.141:5000/nginx
小结:
registry私有仓库设置步骤
1、下载registry镜像 (字符终端)
2、生成registry容器,开放5000端口
3、客户端设置daemon.json文件 (指定私有仓库位置)
4、镜像打标签 docker tag 原镜像名 仓库IP:端口/镜像名
5、上传镜像docker push 仓库IP:端口/镜像名
6、下载镜像 docker pull
7、查看镜像 docker images
生产环境中使用harbor (图形化界面)
在Docker中,为了方便查看容器内产生的数据或者将多个容器中的数据实现共享,就涉及到容器的数据管理操作。管理Docker容器中数据主要有两种方式:数据卷(Data Volumes)和数据卷容器(Data Valumes Containers)。
数据卷:挂载宿主系统的存储空间(宿主与容器间的共享)
数据卷容器:挂载容器的存储空间(容器与容器间的共享)
数据卷是一个供容器使用的特殊目录,位于容器中,可将宿主机的目录挂载到数据卷上,对数据卷的修改操作立刻可见,并且更新数据不会影响镜像,从而实现数据在宿主机与容器之间的迁移。数据卷的使用类似于Linux下对目录进行mount操作
在docker run命令中使用-v选项可以在容器内创建数据卷。多次使用-v选项可创建多个数据卷。使用-v选项可以在创建数据卷的同时,将宿主机的目录挂载到数据卷上使用,以实现宿主机与容器之间的数据迁移。使用–name选项可以给容器创建自定义名称
注意:宿主机本地目录的路径必须使用绝对路径,如果路径不存在,Docker会自动创建相应的路径
① 创建容器并挂载
使用centos镜像创建一个名为web1的容器,并且将宿主机的/var/www目录挂载到容器的/data1目录上
[root@localhost var]#docker run -v /var/www:/data1 --name web1 -it centos /bin/bash
② 创建文件测试
[root@1ef71c70ea80 /]# cd /data1/
[root@1ef71c70ea80 data1]# touch test01
③ 返回宿主机进行查看
[root@localhost var]# cd www/
[root@localhost www]# ls
test01
同理,在宿主机相应的挂载目录中创建数据,在数据卷中也可以访问
如果需要在容器之间共享一些数据,最简单的方法就是使用数据卷容器。数据卷容器就是一个普通的容器,专门提供数据卷给其他容器挂载使用。使用方法:① 首先需要创建一个容器作为数据卷容器 ②之后再其他容器创建时使用–volumes-from挂载数据卷容器中的数据卷使用
#创建数据卷容器
[root@localhost ~]# docker run --name web2 -v /data1 -v /data2 -it centos /bin/bash
#新容器挂载数据卷容器web2
[root@localhost ~]#docker run -it --volumes-from web2 --name db1 centos /bin/bash
新容器挂载了数据卷容器web2,与其共享data1和data2目录
这样就可以通过数据卷同期实现容器之间的数据共享
通过这些机制,即使容器再运行过程中出现故障,用户也不必担心数据发生丢失,如果发生意外,只需快速重新创建容器即可。
Docker提供了映射容器端口到宿主机和容器互联机制来为容器提供网络服务
在启动容器的时候,如果不指定对应的端口,在容器外将无法通过网络来访问容器内的服务。Docker提供端口映射机制来将容器内的服务提供给外部网络访问,实质上就是将宿主机的端口映射到容器中,使得外部网络访问宿主机的端口便可以访问容器内的服务
实现端口映射,需要在运行docker run命令时使用**-P(大写)选项实现随机映射**,Docker会随机映射一个端口范围在49000~49900的端口到容器内部开放的网络端口
[root@localhost ~]# docker run -d -P httpd:latest
在运行docker run命令时使用**-p(小写)选项指定要映射的端口**
[root@localhost ~]# docker run -d -p 11111:80 httpd:latest
容器互联是通过容器的名称在容器间建立一条专门的网络通信隧道从而实现容器的互联。简单点说,就是会在源容器和接收容器之间建立一条隧道,接受容器可以看到源容器指定的信息。在运行docker run命令时使用–link选项可以实现容器之间的互联通信。
格式为:–link name:alias
其中name是要连接的容器名称,alias是这个连接的别名
注意:容器互联是通过容器的名称来执行的,–name选项可以给容器创建一个友好的名称,这个名称是唯一的,如果已经命名了一个相同名称的容器,当要再次使用这个名称的时候,需要先使用docker rm命令来删除之前创建的同名容器
① 创建源容器
#创建并运行容器取名web1,端口号自动映射
[root@localhost ~]# docker run -itd -P --name web1 centos /bin/bash
② 创建接收容器
#创建并运行容器取名web2, 使用–link指定web1连接容器以实现容器互联
[root@localhost ~]# docker run -itd -P --name web2 --link web1:web1 centos /bin/bash
③ 测试容器互联
#进web2容器,使用ping命令查看容器是否能互联互通
此时,可以看到web2与web2已经建立互联关系。Docker在两个互联的容器之间创建了一条安全隧道,而且不用映射他们的端口到宿主机上,从而避免暴露端口给外部网络。