$: docker run -it busybox:latest sh
/ # touch /newfile
/ # exit
# 列出最近创建的容器
$: docker container ls -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c028c091f964 busybox:latest "sh" 13 minutes ago Exited (0) 27 seconds ago upbeat_cohen
# 查询容器的详情
$: docker container inspect c028c091f964
...
# 提交变更, 构建镜像完成
$: docker commit -a JayL -m "add newfile" c028c091f964
sha256:01603f50694eb62e965e85cae2e2327240e4a68861bd0e98a4fb4ee27b403e6d
# 对镜像进行命名, 原镜像ID取前几位就可以了
$: docker image tag 01603f50694eb62e9 busybox:manual
# 验证新镜像
$: docker run busybox:manual ls -al newfile
-rw-r--r-- 1 root root 0 Jun 15 05:25 newfile
FROM busybox:latest
RUN touch /newfile
$: mkdir autobuild && cd autobuild
$: cat < Dockerfile
FROM busybox:latest
RUN touch /newfile
EOF
$: docker build -t busybox:autobuild .
$: mkdir layer && cd layer && touch newfile
$: cat < Dockerfile
FROM scratch
ADD newfile .
EOF
$: docker build -t layer .
# 镜像的构建层历史
$: docker history busybox:autobuild
IMAGE CREATED CREATED BY SIZE COMMENT
845cc5130d2c 17 minutes ago /bin/sh -c touch /newfile 0B
ef46e0caa533 4 days ago /bin/sh -c #(nop) CMD ["sh"] 0B
4 days ago /bin/sh -c #(nop) ADD file:1067e5a... in / 1.21MB
早期的UFS
AUFS
OverlayFS
overlay
overlay2
$: docker info | grep Storage
Storage Driver: overlay2
# 创建
$: docker-machine create ufs
...
Docker is up and running!
# 登录
$: docker-machine ssh ufs
... ok
# 查询 overlay
$: cat /proc/filesystems | grep overlay
nodev overlay
目录 upper, 代表 Container Layer
目录 lower, 代表 Image Layer
目录 merged,代表挂载目录,即合并后的目录
目录 work,必须为空目录,是 overlay 存储驱动挂载所需的工作目录
# 创建一个测试目录
$: mkdir demo && cd demo
# 创建子目录与文件
$: mkdir upper lower merged work
$: touch lower/file1 lower/file2 lower/file3
$: touch upper/file2 upper/file4
# 通过文件内容区分以下file2
$: echo lower > lower/file2
$: echo upper > upper/file2
# 未挂载
$: ls merged
# 目录合并挂载到merged
$: sudo mount -t overlay overlay -olowerdir=lower,upperdir=upper,workdir=work merged
# 挂载完成后
$: ls merged
file1 file2 file3 file4
# file2 使用的是顶层 upper 的file2 文件
$: cat merged/file2
upper
# 新增文件
$: touch merges/file5
$: ls merged/
file1 file2 file3 file4 file5
# 新增文件写在顶层的 upper 文件夹
$: ls upper/
file2 file4 file5
$: ls lower/
file1 file2 file3
# 修改文件 CoW 技术
$: echo mod > merged/file1
$: ls upper/
file1 file2 file4 file5
$: cat upper/file1
mod
$: cat lower/file1
# 删除文件
$: rm merged/file1
$: ls -al upper | grep file1
c--------- 1 root root 0, 0 Jun 17 10:41 file1
$: ls -al lower | grep file1
-rw-r--r-- 1 docker staff 0 Jun 17 10:15 file1
# 多层目录: lower1 / lower2 / lower3
$: sudo mount -t overlay overlay -olowerdir=lower1:lower2:lower3,upperdir=upper,workdir=work merged
mount | grep overlay
overlay on /home/docker/demo/merged type overlay (rw,relatime,lowerdir=lower,upperdir=upper,workdir=work)
$: mkdir autobuild && cd autobuild
$: cat < Dockerfile
FROM busybox:latest
RUN touch /newfile
EOF
$: docker build -t busybox:autobuild .
# 完成构建后,现在系统中有两个docker image
$: docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
busybox autobuild 2e32da74b3ad 4 seconds ago 1.22MB
busybox latest e4db68de4ff2 2 days ago 1.22MB
# docker 无容器运行
$: mount
...
/dev/sda1 on /mnt/sda1/var/lib/docker type ext4 (rw,relatime,data=ordered)
# docker 运行容器时
# 重新开启新会话,运行一个容器实例 `docker run -it busybox:autobuild sh`
$: mount
...
/dev/sda1 on /mnt/sda1/var/lib/docker type ext4 (rw,relatime,data=ordered)
overlay on /mnt/sda1/var/lib/docker/overlay2/a54541dd24971b9491a54b43cdf51f4ef9c87c1cd29748bb3fe64dedafd91b56/merged type overlay (rw,relatime,lowerdir=/mnt/sda1/var/lib/docker/overlay2/l/KLGL6INSJ2UBLMAUP5B4IORUTG:/mnt/sda1/var/lib/docker/overlay2/l/BGIT3WQZVII4Z2THF35I6T5V5O:/mnt/sda1/var/lib/docker/overlay2/l/6GZ2NT4UQT6EQK3IT4IGMBXU4T,upperdir=/mnt/sda1/var/lib/docker/overlay2/a54541dd24971b9491a54b43cdf51f4ef9c87c1cd29748bb3fe64dedafd91b56/diff,workdir=/mnt/sda1/var/lib/docker/overlay2/a54541dd24971b9491a54b43cdf51f4ef9c87c1cd29748bb3fe64dedafd91b56/work)
shm on /mnt/sda1/var/lib/docker/containers/e50f19c5bde3fe53cde3729de92f75b74323f7ebb506b0635eb76dd5b81e080a/mounts/shm type tmpfs (rw,nosuid,nodev,noexec,relatime,size=65536k)
nsfs on /var/run/docker/netns/3c464f8003e8 type nsfs (rw)
挂载后的目录是:/mnt/sda1/var/lib/docker/overlay2/a54541dd24971b9491a54b43cdf51f4ef9c87c1cd29748bb3fe64dedafd91b56/merged
容器 Layer 是:/mnt/sda1/var/lib/docker/overlay2/a54541dd24971b9491a54b43cdf51f4ef9c87c1cd29748bb3fe64dedafd91b56/diff
镜像 Layer 是:/mnt/sda1/var/lib/docker/overlay2/l/KLGL6INSJ2UBLMAUP5B4IORUTG /mnt/sda1/var/lib/docker/overlay2/l/BGIT3WQZVII4Z2THF35I6T5V5O /mnt/sda1/var/lib/docker/overlay2/l/6GZ2NT4UQT6EQK3IT4IGMBXU4T
$: docker inspect -f '{{.GraphDriver.Data.MergedDir}}'
$: docker inspect -f '{{.GraphDriver.Data.UpperDir}}'
$: docker inspect -f '{{.GraphDriver.Data.LowerDir}}'
省钱,减少网络传输流量,节省镜像存储空间
省时,加速镜像部署时间
安全,有限功能降低被攻击的可能性
环保,垃圾都分类了,浪费资源可耻
缩减镜像的Layer大小
减少镜像的Layer层数
FROM debian:stable
WORKDIR /var/www
RUN apt-get update && \
apt-get -y --no-install-recommends install curl \
ca-certificates && \
apt-get purge -y curl \
ca-certificates && \
apt-get autoremove -y && \
apt-get clean
$: docker build --squash -t .
镜像 Scratch(空镜像),大小 0B
镜像 BusyBox(空镜像 + BusyBox),大小 1.4MB
镜像 alpine(空镜像 + BusyBox + apk),大小 3.98MB
FROM golang:1.11-alpine3.7 AS builder
WORKDIR /app
COPY main.go .
RUN go build -o server .
FROM alpine:3.7
WORKDIR /app
COPY --from=builder /app .
CMD ["./server"]
# 通过命令查询出具体镜像的sha256摘要
$: docker inspect busybox:autobuild -f "{{.RepoDigests}}"
sha256:9b63a0eaaed5e677bb1e1b29c1a97268e6c9e6fee98b48badf0f168ae72a51dc
FROM busybox@sha256:9b63a0eaaed5e677bb1e1b29c1a97268e6c9e6fee98b48badf0f168ae72a51dc
...
# 镜像构建过程中增加对特殊权限可执行文件的扫描并删除
RUN for i in $(find / -type f \( -perm +6000 -o -perm +2000 \)); \
do chmod ug-s $i; done
$: CI=true dive
Fetching image... (this can take a while with large images)
Parsing image...
Analyzing image...
efficiency: 95.0863 %
wastedBytes: 671109 bytes (671 kB)
userWastedPercent: 8.2274 %
Run CI Validations...
Using default CI config
PASS: highestUserWastedPercent
SKIP: highestWastedBytes: rule disabled
PASS: lowestEfficiency
rules:
# If the efficiency is measured below X%, mark as failed.
# Expressed as a percentage between 0-1.
lowestEfficiency: 0.95
# If the amount of wasted space is at least X or larger than X, mark as failed.
# Expressed in B, KB, MB, and GB.
highestWastedBytes: 20MB
# If the amount of wasted space makes up for X% or more of the image, mark as failed.
# Note: the base image layer is NOT included in the total image size.
# Expressed as a percentage between 0-1; fails if the threshold is met or crossed.
highestUserWastedPercent: 0.20
$: CI=true dive
容器的构建,讲解了容器的手动构建与自动构建过程。
镜像的存储,讲解了镜像的分层结构以及UnionFS联合文件系统,以及镜像层在UnionFS上的实现。
最小化容器构建,讲解了为什么需要最小化镜像,同时如何进行最小化操作。
容器镜像的加固,容器镜像加固的具体方式。
容器镜像的审查,高质量的项目中容器镜像也需要向代码一样进行审查。