Image 构建
docker commit
docker commit 命令允许用户创建新的镜像,该镜像基于本地配置完成的容器创建。它是通过保存容器的状态并创建一个新的镜像来实现的。docker commit命令的语法如下:
docker commit -m "compile env" -a "xxx" ubuntu xxxx/hub:v1.0.0-ubuntu20.04
docker build
docker build 命令是一种更为灵活和强大的构建镜像的方法,它基于 Dockerfile 创建新的镜像。Dockerfile是一种声明性的文本文件,包含了一系列指令和参数,用于构建Docker镜像。Dockerfile中的指令可以指定镜像的基础镜像、安装依赖项、复制文件、设置环境变量、端口、运行命令等,每一条指令的执行都会创建一个新的镜像层,不断累加,形成一个最终的镜像,需要控制镜像层数,避免镜像过大。
docker build命令
docker build -t {imagename}:{Tag} -f ./dockerfile/
参数:
- -t:指定 Repository 以及Tag,例如 helloworld:1.0
- -f:指定Dockerfile路径,Dockerfile不在当前目录时使用,也是构建的上下文目录
- —pull:构建镜像时总是拉取Base Image的最新版本
- —no-cache:常见镜像的过程中不使用Build Cache构建镜像
Dockerfile常用指令
指令 | 描述 |
---|---|
FROM | 指定基础镜像,可以指定多个,指定多个基础镜像时,编译时也会生成对应的多个镜像 |
MAINTAINER | 指定Dockerfile的作者/维护者 |
WORKDIR | 设置工作目录,后续的RUN、COPY、CMD都将在工作目录下运行,没指定时以构建时的上下文路径为基础 |
RUN | 构建镜像时运行命令,可以用他安装软件等,RUN指令每执行一次都会在 docker上新建一层 |
COPY | 拷贝文件或目录到镜像中,相对路径是docker build -f 指定的路径 |
ADD | 拷贝文件或目录到镜像中,如果源文件是gizp等压缩文件,会被自动解压到目标目录 |
ENV | 设置环境变量,在docker build 过程和镜像内部都存在 |
ARG | 设置的参数仅在docker build 过程中有效,镜像内不存在,使用 docker build –build-arg 会覆盖 |
USER | 为RUN、CMD 和 ENTRYPOINT 执行命令指定运行用户 |
EXPOSE | 声明容器暴露给宿主机的端口,可以是一个或者多个以空格间隔 |
HEALTHCHECK | 指定某个程序或者指令来监控 docker 容器服务的运行状态 |
VOLUME | 用于指定持久化目录,最好是在docker-compose中设置 |
CMD | CMD 指定容器启动时执行的命令,可以被 docker run 中的 COMMAND 和 docker-compose 中的 command 覆盖。如果 Dockerfile 中也有ENTRYPOINT 指定,那么 CMD 中的内容将作为默认参数传递给 ENTRYPOINT 指定的脚本 |
ENTRYPOINT | 运行容器时先执行的程序或脚本,可以被 docker run --entrypoint 指定的脚本覆盖, 参数来自于docker run 中的 COMMAND 和 docker-compose 中 command 或 Dockerfile 中的CMD 指令 |
Dockerfile实例
# /etc/docker/daemon.json 下配置的镜像源下拉取或官方镜像源
FROM ubuntu:20.04
# 指定镜像源拉取镜像
# FROM hub.rat.dev/library/ubuntu:20.04
# 指定在软件安装以非交互式进行
ENV DEBIAN_FRONTEND=noninteractive
# 替换软件源,安装基础软件
RUN sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list && \
sed -i 's/security.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list && \
apt-get update && \
apt-get install locales -y && \
apt-get install -y sudo && \
locale-gen en_US.UTF-8 && \
echo 'root:password' | chpasswd && \
sed -i 's/\/bin\/sh/\/bin\/bash/g' /etc/default/useradd
# 安装开发依赖软件
RUN apt-get install -y git && \
apt-get install -y gcc && \
apt-get install -y make && \
apt-get install -y cmake && \
apt install -y build-essential \
apt-get install -y python3 && \
apt-get install -y python3-pip \
apt-get install -y openssh-server && \
sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
COPY startpoint.sh /startpoint.sh
RUN chmod +x /startpoint.sh
# 设置docker启动的入口函数
ENTRYPOINT ["/startpoint.sh"]
Dockerfile多阶段构建
参考链接:https://cloud.tencent.com/developer/article/1632733
image精简基础镜像
docker 精简基础镜像主要有: scratch 空镜像,需要头开始构建需要的镜像,busybox 带有少量基础的 shell 命令,alpine 是基于 busybox 构建的镜像,并且加入了 apk 包管理器,具体的大小如下,scratch:1.0.0 本身是 0kB,此处的2.7kB 是由于拷贝了一个 hello 的可执行程序。
root@test:~/docker# docker images -a
REPOSITORY TAG IMAGE ID CREATED SIZE
scratch 1.0.0 e53651c2623b 15 minutes ago 2.7kB
busybox latest beae173ccac6 2 years ago 1.24MB
alpine latest c059bfaa849c 2 years ago 5.59MB
ubuntu latest ba6acccedd29 2 years ago 72.8MB
scratch镜像
该镜像是一个空的镜像,可以用于构建busybox等超小镜像,么有shell 终端,没有标准libc库,可以说是真正的从零开始构建属于自己的镜像。
scrath 的拉取不能使用 docker pull,否则会报错,唯一的方式就是使用 Dockerfile 的 FROM scratch 来构建新镜像:
FROM scratch
COPY hello /
CMD ["/hello"]
busybox镜像
busybox 中包含了基本的 shell 命令仅有 1.24MB 大小,可以使用docker pull 直接拉取,通过ldd 发现也没有包含标准glibc库,想要程序运行在busybox 容器上,只能使用静态库的方式编译后运行。
alpine镜像
alpine 镜像的底层使用了 busybox 二进制文件,支持基础的shell 命令,还包含了 apk 包管理器和一些额外的可执行文件,在 alpine 中没有包含标准的glibc库,而是包含了更加轻巧,功能简化的musl libc,如下所示:
musl libc 和标准 glibc 是不兼容的,如下 helloc.c 有如下代码,使用 gcc -o hello main.c 进行编译后拷贝到容器中执行,会出现如下错误:exec /hello: no such file or directory ,所以如果想让程序跑在 Alpine 镜像中,必须在编译时使用 musl libc 作为动态库。
#include <stdio.h>
void main()
{
printf("hello world\n");
}
如果需要支持 libc 就必须安装 build-base,如果安装 gcc,就只有编译器,没有标准库。build-base 相当于 Ubuntu 的 build-essentials,引入了编译器、标准库和 make 之类的工具。Dockerfile 文件如下:
FROM alpine
RUN apk add build-base