3.Dockerfile

Dockerfile

文章目录

1.Layer

1.1为什引入容器镜像分层(layer)

  • 镜像本就是是一个打包文件,但是如果只是打包一个文件我们用manifest即可,为了保证容器运行环境的一致性,镜像必须把应用程序所在操作系统的根目录,也就是 rootfs,都包含进来,虽然这些文件里不包含系统内核,但如果每个镜像都重复做这样的打包操作,仍然会导致大量的冗余,很自然的,我们就会想到,应该把重复的部分抽取出来,只存放一份根目录文件,然后让这一千个镜像以某种方式共享这部分数据

1.2 镜像的内部机制是怎样的

  • 容器镜像,是由许多的镜像层组成的,每层都是只读不可修改的一组文件,相同的层可以在镜像之间共享,然后多个层像搭积木一样堆叠起来,再使用一种叫"Union FS 联合文件系统"(overlay2)的技术把它们合并在一起,就形成了容器最终看到的文件系统

1.3 镜像里的层都是只读不可修改的,但容器运行的时候经常会写入数据,这个冲突应该怎么解决呢

  • docker在挂载镜像文件的时候除了镜像文件的只读层,还会挂载一个'可读写层',在容器运行是,它以copy-on-write的方式,记录容器中的'写'操作

2.Dockerfile基础

  • dockerfile就是编译镜像的施工图纸
  • Docker 镜像遵循的是 OCI (Open Container Initiatve) 标准,所以制作出来的镜像文件也能够被其他的容器技术 (如 Kata、Kubernetes) 识别并运行
shell 复制代码
# 基础镜像
FROM python:3.10-alpine
# 镜像作者
MAINTAINER xiaopawnye
# 环境变量
ENV DJANGO_SETTINGS_MODULE=settings.local
#切换目录
WORKDIR /data/recruitment
#拷贝文件
COPY ./requirements.txt .
COPY ./start.sh .
COPY ./src .
#运行命令
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories # 替换为apk阿里云镜像
# 更新APK
RUN apk add --update --no-cache curl jq py3-configobj py3-pip py3-setuptools python3-dev \
  && apk add --no-cache gcc g++ jpeg-dev zlib-dev libc-dev libressl-dev musl-dev libffi-dev \
  && python -m pip install --upgrade pip \
  && pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple \
  && apk del gcc g++ libressl-dev musl-dev libffi-dev python3-dev \
  && apk del curl jq py3-configobj py3-pip py3-setuptools \
  && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
  && echo 'Asia/Shanghai' >/etc/timezone  \
  && rm -rf /var/cache/apk/*
RUN sed -i 's/\r//' /data/recruitment/start.sh
RUN chmod +x ./start.sh
EXPOSE 39979
CMD ["/bin/sh", "/data/recruitment/start.sh"]
shell 复制代码
# 构建镜像
docker build --network=host -t xiaopawnye/recruitment-base:v1 recruitment/
# 启动镜像
docker run --rm --network=host  -p 39979:39979 -v "$(pwd)":/data/recruitment  --env server_params="--settings=settings.local" xiaopawnye/recruitment-base:v1
#查看构建历史
docker history <镜像名> 

详见:Dockerfile编译Django镜像

3.Dockerfile技巧

  • 每一行的RUN命令都会产生一层image layer,容易导致镜像的臃肿,为此经常写成会将多个命令写成一条命令,末尾使用续行符 \,命令之间也会用 && 来连接

  • 一条命令一旦写错了,每次调试都要重新构建也很麻烦,所以可以采用一种变通的技巧:把这些 Shell 命令集中到一个脚本文件里,用 COPY 命令拷贝进去再用 RUN 来执行

    修改前

    dockerfile 复制代码
    RUN apt-get update \
        && apt-get install -y \
            build-essential \
            curl \
            make \
            unzip \
        && cd /tmp \
        && curl -fSL xxx.tar.gz -o xxx.tar.gz\
        && tar xzf xxx.tar.gz \
        && cd xxx \
        && ./config \
        && make \
        && make clean

    修改后

    dockerfile 复制代码
    COPY setup.sh  /tmp/                # 拷贝脚本到/tmp目录
    
    RUN cd /tmp && chmod +x setup.sh \  # 添加执行权限
        && ./setup.sh && rm setup.sh    # 运行脚本然后再删除
  • ADD和COPY目标目录不存在都会自动创建 ,ADD自动去解压缩文件,不推荐使用ADD(过多的操作让它的含义模糊)

    dockerfile 复制代码
    COPY ./a.txt  /tmp/a.txt    # 把构建上下文里的a.txt拷贝到镜像的/tmp目录
    COPY /etc/hosts  /tmp       # 错误!不能使用构建上下文之外的文件
  • ENV设置的变量可以保存在镜像构建中和容器运行时可见,ARG只在镜像中可见

    dockerfile 复制代码
    ARG IMAGE_BASE="node"
    ARG IMAGE_TAG="alpine"
    
    ENV PATH=$PATH:/tmp
    ENV DEBUG=OFF
  • docker build 需要指定"构建上下文",其中的文件会打包上传到 Docker daemon,所以尽量不要在"构建上下文"中存放多余的文件

    .dockerignore文件

    .dockerignore 复制代码
    # docker ignore
    *.swp
    *.sh
  • 可以使用docker history命令回放完整的镜像的构建过程,有的时候对于镜像排错很有用。

  • 尽量使用非root用户

  • 建议使用exec的列表格式可以使用env环境变量

  • 容器启动命令 CMD,容器启动时默认执行的命令, 启动容器时指定了其它命令,则CMD命令会被忽略

  • 构建缓存

    • 构建时不使用用缓存 docker build --no-cache -t [镜像名]:[镜像版本]

    • 部分使用缓存,dockerfile中指定REFRESH_DATE环境变量

      • ENV REFRESH_DATE 2018-01-12
      • 只要构建的缓存时间不变,那么就用缓存,如果时间一旦改变,就不用缓存了
相关推荐
CodeGolang13 小时前
Docker容器化部署Zabbix监控系统完整指南
docker·容器·zabbix
忆~遂愿14 小时前
Runtime 上下文管理:计算实例的生命周期、延迟最小化与上下文切换优化
java·大数据·开发语言·人工智能·docker
lpruoyu1 天前
【Docker进阶-03】存储原理
docker·容器
文静小土豆1 天前
Docker 与 containerd 代理配置详解:镜像拉取速度慢的终极解决方案
运维·docker·容器
JY.yuyu1 天前
Docker常用命令——数据卷管理 / 端口映射 / 容器互联
运维·docker·容器
lpruoyu1 天前
【Docker进阶-06】docker-compose & docker swarm
运维·docker·容器
虾说羊1 天前
docker容器化部署项目流程
运维·docker·容器
骇客野人1 天前
通过脚本推送Docker镜像
java·docker·容器
人鱼传说1 天前
docker desktop是一个好东西
运维·docker·容器