制作Docker业务镜像
随着容器云的迅猛发展,不断有业务需要Docker化。以下是笔者在制作Docker镜像中的一些浅见,希望能对大家有所帮助, 若有错误之处,欢迎大家指正与探讨。
基础镜像介绍
镜像仓库为大家提供了高效便捷的基础镜像,其中不仅包含安全所需的Onion Agent,还有发布平台、TGW等公司其他业务Agent, 减轻了大家制作业务镜像的负担。
1.tlinux2.2-gaia-with-onion:latest
服务列表 : 该基础镜像包含了安平的Onion Agent,制作业务镜像的时候无需再重新安装相应的组件,省去了不必要的重复性工作。完整镜像名称
docker.oa.com:8080/library/tlinux2.2-gaia-with-onion:latest
- onion agent
使用方法 :该镜像作为基础镜像,继承镜像需要先启动onion agent. 启动方式为:bash +x /usr/local/onion-start.sh
2、tlinux2.2-with-agent:latest
服务列表 : 当业务需要接入TGW、L5等,可以使用该镜像作为基础镜像。该基础镜像不仅包含必备的Onion组件,还包含了TGW、L5、发布平台等公司其他业务Agent。在制作业务镜像的时候只需专注业务逻辑,无需再关注各种Agent的安装。完整镜像名称
docker.oa.com:8080/public/tlinux2.2-with-agent:latest
- ssh
- crontab
- L5 agent
- tnm2 agent
- TSC Agent
- publish platform agent
- dns setting
onion agent
开放端口:
- 8080
- 80
36000
使用方法 :该镜像作为基础镜像,继承镜像需要先启动所有agent. 启动方式为:bash +x /usr/local/all-agent-start.sh
镜像制作示例
1、DockerFile 示例
此处忽略DockerFile的各个指令介绍,Docker 官方网站有最全最详细的介绍文档。 ```
NAME Hello World Go With Onion Agent
Time 2017/5/11
VERSION 1.0.0
FROM docker.oa.com:8080/public/tlinux2.2-with-agent MAINTAINER elsanli [email protected] LABEL version="1.0" LABEL description="This Dockerfile is written for Hello World Go."
RUN yum -y update && \ yum install -y libstdc++.so.6 mariadb && \ yum clean all && \ rm -rf /tmp/ /var/tmp/ /data/tmp/* EXPOSE 36000 8080 80 WORKDIR /usr/local/
GO
COPY go1.6.3.linux-amd64.tar.gz ./ RUN tar zxvf go1.6.3.linux-amd64.tar.gz && mv go go1.6
ADD main.go /usr/local/go/ RUN cd go && chmod -v +x main.go
ADD run.sh ./ RUN chmod -v +x run.sh CMD ["/usr/local/run.sh"]
#### 2、Build
>       通常也可以将REPOSITORY设置为:业务名称/组件名称,方便管理。
docker build -t docker.oa.com:8080/public/hello-world-go:latest ./
#### 3、Push镜像到镜像仓库
>       可以将镜像Push到镜像仓库中进行保存。 Push镜像一分钟后,可以移步到 [GaiaStack体验环境](gaiastack.oa.com) 镜像仓库查看镜像,进行应用部署,并可以灵活绑定云硬盘,在线扩容等。若利用`GaiaStack`平台部署应用可以`略过步骤4-5`。
> GaiaStack镜像仓库支持个人镜像、业务镜像、公有镜像。
   - 个人镜像:rtx名称/镜像名称:tag `仅用户本人有权查看与部署`
   - 业务镜像:业务名称/镜像名称:tag (`其业务名称为:GaiaStack平台中业务组名称`) `仅同业务组人员有权查看与部署`
   - 公有镜像: public/镜像名称:tag    docker/镜像名称:tag   library/镜像名称:tag `所有人有权查看与部署`
docker push docker.oa.com:8080/public/hello-world-go:latest
#### 4、启动容器
docker run -d docker.oa.com:8080/public/hello-world-go:latest
#### 5、登录容器
查看docker进程: docker ps
![Alt text](./1500463985616.png)
可以通过容器id登录容器: docker exec -it 645a767d59aa /bin/sh
## 精简镜像大小
>      由于Docker容器的文件系统采用了写入时拷贝技术,这项技术的作用是加快容器的启动时间,跟一般的虚拟机相比,容器的启动速度确实非常快。虽然该技术在很大程度上提升了docker容器的运行效率,但是也会增加磁盘读写方面的开销。 同时也为了避免大量时间都花费在等待镜像的回来传送上,精简镜像大小是非常有必要的。
#### 1、减少镜像Layer层数
      每次在Dockerfile中执行RUN命令的时候系统都会在镜像中新建一个层,每个镜像层都会占用一定的磁盘空间,因此为了尽量减少镜像的层数,最好把解压、删除等所有文件操作都写在同一行RUN命令下。可以看下下面的例子:
**错误示范**
```dockerfile
RUN tar zxvf go1.6.3.linux-amd64.tar.gz
RUN mv go go1.6
通过docker history查看,可以看到tar zxvf创建了一个大小为318.1MB的镜像层,而mv命令在它上面又创建了一个318.1MB的镜像层。
正确示范
RUN tar zxvf go1.6.3.linux-amd64.tar.gz && mv go go1.6
将tar zxvf操作与mv操作放在同一行RUN命令中,可以查看到, mv操作并没有再创建一个镜像层。
2、迁移数据
不要把训练数据等直接COPY到镜像中,由于数据往往过于庞大,不仅占用存储空间,致使性能下降,更会导致敏感数据泄露。可以利用分布式文件系统、数据库等存储数据。比如将存储在 GaiaStack云平台的云硬盘(cephfs、ceph rbd)中,在部署应用的时候挂载该云硬盘,从而使用数据。
3、有效删除不必要文件
在下载压缩包或者其他归档文件的时候,可以将其解压,以及立即删除归档文件。但前提是这几个操作还是要在同一个RUN命令下。
RUN yum -y update && \
yum install -y libstdc++.so.6 mariadb && \
yum clean all && \
rm -rf /tmp/* /var/tmp/* /data/tmp/*
其他注意事项
1、当心latest标签
不要误以为latest版本镜像是最新与最稳定的版本镜像,这可能是个惯例,但并不是出于任何严格的规定。与所有其他版本镜像一样,当有新的版本push到镜像仓库中,latest标签的镜像也不会自动更新。
2、不要在DockerFile中启动进程
DockerFile的每个step都是在一个临时的container执行的,DockerFile里启动的进程并不会在之后的容器里启动。
3、当心/etc/resolv.conf
直接将修改好的resolve.conf 文件在DockerFile中COPY到镜像里,当容器启动时候,会被宿主机resovle.conf覆盖。
4、tag充分体现版本变更
若某个NODE节点上已经有了某个版本的镜像,若该版本镜像(latest除外)内容有所修改,虽然已经上传到镜像仓库中,在该节点上在利用该镜像启动容器,Docker是不会再从镜像仓库拉取新的镜像,所以tag要充分体现版本变更。
FAQ
1、 为何Docker容器内部无法解析域名
有的基础镜像默认没有打开IP转发功能,可以通过查看proc文件系统,来确认IP转发功能状态。 如果文件中的值为0,则说明禁止IP转发,如果为1,这说明已经打开IP转发功能。
如果IP转发被禁止,可以将net.ipv4.ip_forward
参数修改为1 ,打开IP转发功能。
2、为何在 Docker容器中修改hosts文件,重启后无效
容器中/etc/hosts文件不存在于镜像,而是存在宿主机中,在启动容器的时候,通过mount的形式将该文件挂载到容器内部。因此,如果在容器中修改这些文件的话,修改部分不会存在于容器的top layer,而是直接写入物理文件中。每次Docker在启动容器的时候,都会重新构建新的/etc/hosts文件,所以原先修改内容会被Docker自动给覆盖掉。
可以通过docker run命令的--add-host
参数来为容器添加host与IP的映射关系。
3、Docker容器如何修改/proc/sys/kernel/shmmax等内核参数
在容器中修改特定参数,结果提示this is a rad-only file。这是因为默认情况下,Docker的container是没有特权的,并未拥有真正的root权限,是不能修改系统参数的。可以通过--privileged选项,使容器获取额外的特权,从而修改系统参数。
4、在Build镜像时,指定了--shm-size大小,但是镜像启动之后发现没有生效
因为Docker build 的shm参数是指定构建镜像过程中的container的shm大小,实际镜像运行的shm大小要通过docker run --shm-size来指定。但是要注意的是, --shm-size设定的数值要小于系统变量SHMMAX数值,否则会报错,可以通过sysctl -a|grep shmmax进行查看。