杨世威

个人站

欢迎来到我的个人站~


Docker从入门到使用系列

Get Started with Docker

我都不喜欢照搬官网教程,就从一些示例来说,这样比较快速了解docker
从nginx的官网docker镜像入门,理解docker
Nginx-Docker镜像地址
能看到,有很多tag的镜像版本:

  • 镜像标注了nginx的版本:mainline和stable,分别表示开发版(主力版)和稳定版(生产环境建议版本)
  • 标注了基础镜像版本:stretch(debain)和alpine

主要讲一下基础镜像,所有的dockerfile第一段都是用FROM开头,标明这个dockerfile是在什么镜像的基础上编写的
作为最底层的基础镜像,就像虚拟机里面的操作系统
Alpine:优点 小,快,安全

  • 一个alpine的基础镜像只有不到4M,debain差不多120+M
  • alpine的速度快,拉取依赖的速度快
  • 因为小,默认不安装bash解释器,漏洞少

使用Alpine作为基础镜像需要注意的点参考博客

  • 库问题
  • DNS问题

alpine仓库中很多已经编译好的二进制服务的软件包是依赖于alpine的musl libc库
安装这些服务包只需要apk add xxx 直接安装
仓库中没有的服务包,同时这些服务包依赖于glibc的软件,则需要提前在alpine基础镜像中安装glibc库 gs

RUN apk --no-cache add ca-certificates && \
    wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://raw.githubusercontent.com/sgerrand/alpine-pkg-glibc/master/sgerrand.rsa.pub && \
    wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.27-r0/glibc-2.27-r0.apk && \
    apk add glibc-2.27-r0.apk

Dns问题官方给出的解释还是和musl libc库有关系
总结下来就是musl实现的DNS服务不会使用resolv.conf文件中的search和domain两个配置
github官方解释

  • 一是在使用dns作为服务发现时
  • 二是在使用并行的dns服务器时,不能确保前一个一直作为默认的dns服务器 –dns xxx1 –dns xxx2

推荐使用dnsmasq,运行时使用–server /consul/10.0.0.1这个参数

FROM alpine:edge
RUN apk --no-cache add dnsmasq
EXPOSE 53 53/udp
ENTRYPOINT ["dnsmasq", "-k"]

从Nginx的dockerfile来理解docker

FROM alpine:3.8

LABEL maintainer="NGINX Docker Maintainers <docker-maint@nginx.com>"

ENV NGINX_VERSION 1.14.2

RUN GPG_KEYS=B0F4253373F8F6F510D42178520A9993A1C052F8 \
	***
	&& ln -sf /dev/stderr /var/log/nginx/error.log

COPY nginx.conf /etc/nginx/nginx.conf
COPY nginx.vh.default.conf /etc/nginx/conf.d/default.conf

EXPOSE 80

STOPSIGNAL SIGTERM

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

上文dockerfile,RUN部分的代码省略了,下面做命令的简单解释:
RUN命令用\ &&连接很多命令,因为docker是层的概念,每增加一个指令相当于在镜像上添加一层,所以用连接符将多个命令连接成一个RUN

  • FROM: 前面已经说了,声明基础镜像,声明这个dockerfile是基于哪个镜像来生成的
  • LABEL: 没啥作用,标注作者用的
  • ENV: 环境变量声明,类似语言中申明变量一样
  • RUN: 运行命令,一般用户构建过程中的指令,RUN执行的命令是在构建镜像过程中,在基于FROM的基础镜像的系统上执行的命令,所以RUN里面的命令风格要和FROM指定的基础镜像一致,比如上面基于alpine的nginx安装时,RUN时安装包则用apk add
  • CP: 将宿主机的文件拷贝到镜像内
  • EXPOSE: 指定镜像端口
  • CMD: 最后运行指定,多个时以最后一个为准,CMD只会执行最后一条

dockerfile打包的规则是打出尽量小的镜像,多指令通过连接符、–no-cache,删除过程文件均是为了最小化镜像
在docker17.05之后,docker支持了多阶段构建的-multi-stage build
通过多阶段构建,解决依赖构建过程,造成镜像包大的问题,因为安装的构建服务只会使用一次
使用也很简单

FROM golang:1.7.3
WORKDIR /go/src/github.com/sparkdevo/href-counter/
RUN go get -d -v golang.org/x/net/html
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
 
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=0 /go/src/github.com/sparkdevo/href-counter/app .
CMD ["./app"]

可以看到多阶段构建
第一阶段即进行依赖构建,将构建好的依赖包拷贝出来
第二阶段将打好包的依赖CP进去,启动服务

这样最终生成的镜像仅包含第二阶段的内容,而没有仅仅打包时需要安装的一些库。从而更加精简了docker镜像
日常使用下来,真正需要手动编写的dockerfile很少,大部分是基于docker官方镜像仓库编好的镜像进行改写
比如在编写好的nginx增加一个插件,FROM nginx:xxx 然后安装插件,即可

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦