fedora镜像(采用tini替代systemd)

虽然我构建的  Fedora 镜像 (使用 systemd 作为 init 进程管理器)能够完美在 Docker 中运行,但是迁移到  Kubernetes Atlas  中运行( kind 部署 fedora-dev )却无法正确初始化  Systemd 进程管理器 。我尝试采用 Docker 默认的 init 管理器  Docker tini 进程管理器  来再次尝试构建镜像,以期能够在  kind 部署 fedora-dev-tini (tini 替代 systmed)

备注

由于使用  从 Dockerfile 构建 Docker 镜像  重复构建镜像时,需要重复在容器内部执行各种软件包安装下载,非常消耗时间。为了能够节约部署时间(特别是局域网内部),我采用在  Kubernetes 部署 Squid  在我的  kind(本地 docker 模拟 k8s 集群) ( macOS 工作室 ) ,这样不断重复相同操作系统的安装升级可以节约时间和带宽。

由于 Docker 镜像制作需要反复测试,容器内部 OS 更新和软件安装会不断重复,所以为了加快进度和节约带宽,采用  Docker 客户端的 Proxy  配置来加速: (注意:这里首先需要在 docker 集群中部署  Docker 环境运行 Squid  代理容器,然后通过  Docker 客户端的 Proxy  配置为所有 docker 容器注入使用代理服务器访问外网来加速下载)

  • 修改  ~/.docker/config.json :

采用默认 docker 网络 bridge 上部署的  Docker 环境运行 Squid  代理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
{
  "credsStore": "desktop",
  "proxies":
  {
    "default":
    {
      "httpProxy": "http://172.17.0.3:3128",
      "httpsProxy": "http://172.17.0.3:3128",
      "noProxy": "*.baidu.com,192.168.0.0/16,10.0.0.0/8"
    }
  }
}
  • 还有一个问题需要解决: 默认  DNF 包管理器  会使用  mirrors.fedoraproject.org  来侦测最快的镜像网站,但是实际上每次选择可能都是不同网站,这导致代理服务缓存效果很差。解决的思路是注释掉  metalink=  行,启用固定的  baseurl=  行 ( How to disable some mirrors for use by dnf in Fedora [closed]  提及原先  yum-plugin-fastestmirror  被移植到 dnf 时没有移植参数调整功能 )

我采用  sed  修订  /etc/yum.repos.d  目录下配置:

关闭 dnf 镜像列表功能,指定固定软件仓库以便优化使用 proxy 代理缓存

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
REPO_DIR=/etc/yum.repos.d
BACKUP_DIR=/root/yum.repos.d

# backup
cp -R ${REPO_DIR} ${BACKUP_DIR}

cd ${REPO_DIR}/
# download.example/pub/fedora/linux  =>  mirrors.163.com/fedora
rm fedora-cisco-openh264.repo
sed -i 's/metalink=/#metalink=/g' *
sed -i 's/#baseurl=/baseurl=/g' *
sed -i 's/download.example\/pub\/fedora\/linux/mirrors.163.com\/fedora/g' *
cp ${BACKUP_DIR}/fedora-cisco-openh264.repo ${REPO_DIR}/

这里有一个  fedora-cisco-openh264.repo  配置文件没有提供  baseurl= ,实际这个只有一个下载地址,所以跳过替换

下文我将脚本融入  从 Dockerfile 构建 Docker 镜像  中执行

  • 初始构建一个基础 fedora:

基础 Fedora 镜像 Dockerfile

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
FROM fedora:latest

# set china repo: mirros.163.com
RUN cp -R /etc/yum.repos.d /root/yum.repos.d
RUN rm /etc/yum.repos.d/fedora-cisco-openh264.repo
RUN sed -i 's/metalink=/#metalink=/g' /etc/yum.repos.d/*
RUN sed -i 's/#baseurl=/baseurl=/g' /etc/yum.repos.d/*
RUN sed -i 's/download.example\/pub\/fedora\/linux/mirrors.163.com\/fedora/g' /etc/yum.repos.d/*
RUN cp /root/yum.repos.d/fedora-cisco-openh264.repo /etc/yum.repos.d/

RUN dnf clean all
RUN dnf -y update

ENTRYPOINT ["/usr/bin/bash"]
  • 构建  fedora-base-tini  镜像:

构建基础 Fedora 镜像 Dockerfile

docker build -t fedora-base-tini .

  • 运行  fedora-base-tini  镜像:

运行 fedora-base-tini 容器

docker run -dt –name fedora-base-tini –hostname fedora-base-tini fedora-base-tini

  • 连接到  fedora-base-tini  容器内:

通过 docker exec 运行容器内部 bash

docker exec -it fedora-base-tini /bin/bash

备注

How to enable SSH connections into a Kubernetes pod  提供了一个更好的部署 SSH key 的  使用 ConfigMap 配置 Pod  方法,适合对不同用户在部署 pods 时候注入 SSH key 和构建用户 HOME 目录,后续借鉴实践。

按照  Docker tini 进程管理器  经验总结,采用以下方法实现 Docker 容器内通过  Systemd 进程管理器  运行 ssh,实现一个初始完备的远程可登录  Fedora  系统:

包含 tini 和 ssh 的 Fedora 镜像 Dockerfile

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# USE DOCKER BUILD
# docker build --rm -t fedora-ssh-tini .
# USE DOCKER RUN
# docker run -itd --privileged=true -p 1122:22 --hostname fedora-ssh-tini --name fedora-ssh-tini fedora-ssh-tini

# USE nerdctl (containerd) BUILD
# nerdctl build -t fedora-ssh-tini .

# INTERACT RUN
# nerdctl run -it --privileged=true -p 1122:22 --hostname fedora-ssh-tini --name fedora-ssh-tini fedora-ssh-tini:latest

# BACKGROUND RUN
# nerdctl run -d --privileged=true -p 1122:22 --hostname fedora-ssh-tini --name fedora-ssh-tini fedora-ssh-tini:latest

FROM fedora:latest
MAINTAINER vincent huatai <vincent@huatai.me>

ENV container docker

# set china repo: mirros.163.com
RUN cp -R /etc/yum.repos.d /root/yum.repos.d
RUN rm /etc/yum.repos.d/fedora-cisco-openh264.repo
RUN sed -i 's/metalink=/#metalink=/g' /etc/yum.repos.d/*
RUN sed -i 's/#baseurl=/baseurl=/g' /etc/yum.repos.d/*
RUN sed -i 's/download.example\/pub\/fedora\/linux/mirrors.163.com\/fedora/g' /etc/yum.repos.d/*
RUN cp /root/yum.repos.d/fedora-cisco-openh264.repo /etc/yum.repos.d/

RUN dnf clean all
RUN dnf -y update

# Add Tini
ENV TINI_VERSION v0.19.0
# 标准方法是采用ADD方式向镜像添加tini,但是GFW阻碍,改为下载后本地复制
#ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini
COPY tini /tini
RUN chmod +x /tini
ENTRYPOINT ["/tini", "--"]

# Copy tini entrypoint script
COPY entrypoint_ssh_cron_bash /entrypoint.sh
RUN chmod +x /entrypoint.sh

# Fedora docker image not include systemd,install systemd by initscripts
RUN dnf -y install which sudo passwd openssh-clients openssh-server

# add account "admin" and give sudo privilege
RUN groupadd -g 505 admin
RUN useradd -g 505 -u 505 -d /home/admin -m admin
RUN usermod -aG wheel admin
RUN echo "%wheel        ALL=(ALL)       NOPASSWD: ALL" >> /etc/sudoers

# set TIMEZONE to Shanghai
RUN unlink /etc/localtime && ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

# Add ssh public key for login
RUN mkdir -p /home/admin/.ssh
COPY authorized_keys /home/admin/.ssh/authorized_keys
RUN chown -R admin:admin /home/admin/.ssh
RUN chmod 600 /home/admin/.ssh/authorized_keys
RUN chmod 700 /home/admin/.ssh

RUN ssh-keygen -A

# run service when container started - sshd
EXPOSE 22:1122

# Run your program under Tini
# CMD ["/your/program", "-and", "-its", "arguments"]
CMD ["/entrypoint.sh"]

其中,使用的  entrypoint.sh  脚本是  kind 部署 fedora-dev-tini (tini 替代 systmed)  实践中改进过的脚本:

/entrypoint.sh  脚本的  main()  确保持续运行(循环)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#!/usr/bin/env bash

sshd() {
    /usr/sbin/sshd
}

crond() {
    /usr/sbin/crond
}

main() {
    sshd
    crond
    # 在k8s不能直接bash执行结束,否则判断为pod Crash,需要改写成持续执行循环脚本
    #/bin/bash
    /bin/bash -c "while true; do (echo 'Hello from tini'; date; sleep 120); done"
}

main
  • 构建  fedora-ssh-tini  镜像:

构建包含 tini 和 ssh 的 Fedora 镜像

docker build –rm -t fedora-ssh-tini .

  • 运行  fedora-ssh-tini :

运行包含 tini 和 ssh 的 Fedora 容器

docker run -itd -p 1122:22
–hostname fedora-ssh-tini –name fedora-ssh-tini fedora-ssh-tini

在  fedora-ssh-tini  基础上,增加开发工具包安装:

  • fedora-dev-tini  包含了安装常用工具和开发环境,并编译和安装必要的 vim 环境:

包含常用工具和开发环境的 Fedora 镜像 Dockerfile

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

# USE DOCKER BUILD
# docker build --rm -t fedora-dev-tini .
# USE DOCKER RUN
# docker run -itd --privileged=true -p 1122:22 --hostname fedora-dev-tini --name fedora-dev-tini fedora-dev-tini

# USE nerdctl (containerd) BUILD
# nerdctl build -t fedora-dev-tini .

# INTERACT RUN
# nerdctl run -it --privileged=true -p 1122:22 --hostname fedora-dev-tini --name fedora-dev-tini fedora-dev-tini:latest

# BACKGROUND RUN
# nerdctl run -d --privileged=true -p 1122:22 --hostname fedora-dev-tini --name fedora-dev-tini fedora-dev-tini:latest

FROM fedora:latest
MAINTAINER vincent huatai <vincent@huatai.me>

ENV container docker

# set china repo: mirros.163.com
RUN cp -R /etc/yum.repos.d /root/yum.repos.d
RUN rm /etc/yum.repos.d/fedora-cisco-openh264.repo
RUN sed -i 's/metalink=/#metalink=/g' /etc/yum.repos.d/*
RUN sed -i 's/#baseurl=/baseurl=/g' /etc/yum.repos.d/*
RUN sed -i 's/download.example\/pub\/fedora\/linux/mirrors.163.com\/fedora/g' /etc/yum.repos.d/*
RUN cp /root/yum.repos.d/fedora-cisco-openh264.repo /etc/yum.repos.d/

RUN dnf clean all
RUN dnf -y update

# Add Tini
ENV TINI_VERSION v0.19.0
# 标准方法是采用ADD方式向镜像添加tini,但是GFW阻碍,改为下载后本地复制
#ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini
COPY tini /tini
RUN chmod +x /tini
ENTRYPOINT ["/tini", "--"]

# Copy tini entrypoint script
COPY entrypoint_ssh_cron_bash /entrypoint.sh
RUN chmod +x /entrypoint.sh

# not need systemd(initscripts)
RUN dnf -y install which sudo passwd openssh-clients openssh-server \
    vim iproute net-tools bind-utils bzip2 tmux sysstat nfs-utils lsof \
    procps tree file mlocate rsync cronie cronie-anacron \
    git gdb openssl-devel \
    nodejs

# add account "admin" and give sudo privilege
RUN groupadd -g 505 admin
RUN useradd -g 505 -u 505 -d /home/admin -m admin
RUN usermod -aG wheel admin
RUN echo "%wheel        ALL=(ALL)       NOPASSWD: ALL" >> /etc/sudoers

# set TIMEZONE to Shanghai
RUN unlink /etc/localtime && ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

# Add ssh public key for login
RUN mkdir -p /home/admin/.ssh
COPY authorized_keys /home/admin/.ssh/authorized_keys
RUN chown -R admin:admin /home/admin/.ssh
RUN chmod 600 /home/admin/.ssh/authorized_keys
RUN chmod 700 /home/admin/.ssh

RUN ssh-keygen -A

# run service when container started - sshd
EXPOSE 22:1122

# Run your program under Tini
# CMD ["/your/program", "-and", "-its", "arguments"]
CMD ["/entrypoint.sh"]

fedora-dev-tini  镜像说明

功能 参考
docker 容器运行 ssh 服务 Docker systemd 进程管理器
用户目录 ssh 配置 ssh 密钥
fedora 开发环境 Fedora
  • 构建  fedora-dev-tini  镜像:

构建包含开发环境的 Fedora 镜像

docker build –rm -t fedora-dev-tini .

  • 运行  fedora-dev-tini :

运行包含开发环境的 Fedora 容器

docker run -itd -p 1122:22
–hostname fedora-dev-tini –name fedora-dev-tini fedora-dev-tini

警告

在  kind 部署 fedora-dev-tini (tini 替代 systmed)  实践中发现,上述  fedora-dev-tini  和  fedora-ssh-tini  都会  Crash ,原因是  /entrypoint.sh  脚本直接运行结束,会被 Kubernetes 判断为程序 Crash 。所以,实际  /entrypoint.sh  需要改写成最后执行的  bash  命令永不结束!!!这个很重要,不然部署的景象总是 compelete 状态,无法保持运行中。

Licensed under CC BY-NC-SA 4.0
最后更新于 Jan 06, 2025 05:52 UTC
comments powered by Disqus
Built with Hugo
主题 StackJimmy 设计
Caret Up