大部分的镜像制作都是通过 Dockerfile 来实现的,基本都是基于基础镜像制作,这里介绍使用 buildah
来构建基础镜像,可以以此理解其基本原理。
简介
通过 Buildah
从头搭建一个镜像,这里会制作一些常见的镜像,详细可以查看 GitHub 中的介绍。
----- 用来初始化当前的工作路径
container=$(buildah from scratch)
mountpoint=$(buildah mount $container)
----- 可以通过如下方式清理
buildah containers
buildah unmount working-container
buildah rm working-container
----- 最暴力的清理所有
buildah rm --all
----- 增加EntryPoint,其中前者会默认增加 /bin/bash -c 前缀,等价于 /bin/bash -c "/pause"
buildah config --entrypoint /pause $container
buildah config --entrypoint '["/pause"]' $container
在打包前,建议使用 buildah run $container bash
进入到容器中运行所需的程序,否则经常会因为一些异常导致实际容器运行异常。
制作完镜像后可以通过 rsync -ave ssh mysql.tar slave1:/root
命令将其同步到相关服务器。
常用镜像
如下简单列举一些常用的示例。
pause
用来回收子进程,有点类似 Linux 系统中 init
的作用,同时作为 Pod 中 namespace 的占用。源码在 GitHub 中,其中 orphan.c
为测试使用,可以暂时忽略,可以直接编译,然后添加到镜像的根目录下即可。
gcc -Os -Wall -Werror -static -o pause pause.c
strip pause
buildah copy $container pause / ---> 或者 cp pause $mountpoint/
buildah config --entrypoint '["/pause"]' $container
buildah commit --format docker $container pause
podman save --compress -o pause.tar pause
docker load -i pause.tar
docker tag localhost/pause:latest k8s.gcr.io/pause:3.2
docker rmi localhost/pause
注意,可以先确定报错时使用的 pause
版本号是那个,然后再指定对应 tag
信息,可以从 kubelet
的日志或者通过 kubectl cluster-info dump
命令查看,当前一般就是 3.2
版本。
alpine
如果已经有 rootfs
了,那么可以在执行 mount
之后将其复制到 $mountpoint
目录下即可,例如 alpinelinux 中的。
cp rootfs/* $mountpoint
buildah run $container /bin/sh
buildah commit --format docker $container alpine
podman save --compress -o alpine.tar alpine
docker load -i alpine.tar
docker tag localhost/alpine:latest alpine:latest
CentOS
如果只是单独运行,其实完全可以只添加对应的二进制及其依赖,但考虑到需要登录容器排查问题,所以通常会打包一个包含基础包以及 bash 的镜像。
dnf install --installroot $mountpoint --releasever 1 bash coreutils mysql -y
dnf clean --installroot $mountpoint all
yum install --installroot $mountpoint --release ${distrorelease} bash coreutils \
--setopt install_weak_deps=false -y
yum clean --installroot $mountpoint all
buildah run $container bash
buildah commit --format docker $container centos
podman images
podman run -it centos bash
这里实际以及安装完成,后面介绍一些其它可选的操作
FILE=runecho.sh
/bin/cat <<EOM >$FILE
#!/usr/bin/env bash
for i in {1..9}; do
echo "Hello World"
done
EOM
chmod +x $FILE
buildah copy $container $FILE /usr/bin
buildah run $container /usr/bin/runecho.sh
buildah config --entrypoint /usr/bin/runecho.sh $container
buildah config --author "Andy" --created-by "Andy" --label name=${centos} $container
buildah inspect $container
podman run -t centos
docker load -i centos.tar
docker tag localhost/centos:latest centos:latest
docker rmi localhost/centos
Nginx
dnf install --installroot $mountpoint --releasever 1 bash coreutils nginx -y
dnf clean --installroot $mountpoint all
/bin/cat <<EOM >/tmp/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World</title>
</head>
<body>
<p>Hey</p>
</body>
</html>
EOM
buildah copy $container /tmp/index.html /usr/share/nginx/html/
buildah config --entrypoint '["/usr/sbin/nginx","-g","daemon off;"]' $container
buildah commit --format docker $container nginx
podman save --compress -o nginx.tar nginx
docker load -i nginx.tar
docker tag localhost/nginx:latest nginx:latest
docker rmi localhost/nginx
curl 127.1:80
CoreDNS
CoreDNS 通过 GoLang 编写,部署时实际只使用一个二进制文件即可。
buildah copy $container /etc/ssl/certs /etc/ssl/certs
buildah copy $container coredns /
buildah config --port 53 --port 53/udp $container
buildah config --entrypoint '["/coredns"]' $container
buildah commit --format docker $container coredns
podman save --compress -o coredns.tar coredns
docker load -i coredns.tar
docker tag localhost/coredns:latest coredns/coredns:1.8.3
docker rmi localhost/coredns
详细可以查看 Dockerfile 中的介绍。
MySQL
可以直接参考官方的 Dockerfile 文件,需要将一些相关的脚本文件复制过来,简化后的 Dockerfile
文件如下。
FROM localhost/centos:latest
RUN yum install -y mysql-server && yum clean all
RUN mkdir /docker-entrypoint-initdb.d
COPY prepare-image.sh /
RUN /prepare-image.sh && rm -f /prepare-image.sh
ENV MYSQL_UNIX_PORT /var/lib/mysql/mysql.sock
COPY docker-entrypoint.sh /entrypoint.sh
COPY healthcheck.sh /healthcheck.sh
ENTRYPOINT ["/entrypoint.sh"]
HEALTHCHECK CMD /healthcheck.sh
EXPOSE 3306 33060 33061
CMD ["mysqld"]
dnf install --installroot $mountpoint --releasever 1 bash coreutils mysql-server mysql -y
dnf clean --installroot $mountpoint all
buildah mkdir $container /docker-entrypoint-initdb.d
buildah copy $container prepare-image.sh /
buildah run $container /prepare-image.sh && rm -f /prepare-image.sh
buildah config --env MYSQL_UNIX_PORT=/var/lib/mysql/mysql.sock $container
buildah copy $container docker-entrypoint.sh /entrypoint.sh
buildah copy $container healthcheck.sh /healthcheck.sh
buildah config --entrypoint '["/entrypoint.sh"]' $container
buildah config --healthcheck /healthcheck.sh $container
buildah config --port 3306 --port 33060 --port 33061 $container
buildah config --cmd 'mysqld' $container
buildah commit --format docker $container mysql
podman save --compress -o mysql.tar mysql
docker load -i mysql.tar
docker tag localhost/mysql:latest mysql:latest
docker rmi localhost/mysql
使用时可以通过环境变量进行定制化配置,如下是常见配置:
MYSQL_ROOT_PASSWORD
设置ROOT密码。MYSQL_USER
通常为业务用户。MYSQL_PASSWORD
业务用户密码。MYSQL_DATABASE
业务数据库。
而且,允许用户在 /docker-entrypoint-initdb.d
目录下设置一些常见的初始化脚本。