Ubuntu镜像(采用tini替代systemd)¶
备注
由于使用 从Dockerfile构建Docker镜像 重复构建镜像时,需要重复在容器内部执行各种软件包安装下载,非常消耗时间。为了能够节约部署时间(特别是局域网内部),我采用在 Kubernetes部署Squid 在我的 kind(本地docker模拟k8s集群) ( macOS工作室 ) ,这样不断重复相同操作系统的安装升级可以节约时间和带宽。
我构建基于 Ubuntu Linux 的Android开发环境,基于 Ubuntu镜像(采用tini替代systemd) 修改,来实现一个轻量级的Ubuntu通用开发环境。这样我的实践就覆盖了 RedHat Linux 系(rpm)和 Debian系(apt)两个主流发行版的Docker镜像。
准备工作¶
由于Docker镜像制作需要反复测试,容器内部OS更新和软件安装会不断重复,所以为了加快进度和节约带宽,采用 Docker客户端的Proxy 配置来加速: (注意:这里首先需要在docker集群中部署 Docker环境运行Squid 代理容器,然后通过 Docker客户端的Proxy 配置为所有docker容器注入使用代理服务器访问外网来加速下载)
修改
~/.docker/config.json
:
{
"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"
}
}
}
tini运行ssh ubuntu-ssh-tini
¶
备注
How to enable SSH connections into a Kubernetes pod 提供了一个更好的部署SSH key的 使用ConfigMap配置Pod 方法,适合对不同用户在部署pods时候注入SSH key和构建用户HOME目录,后续借鉴实践。
我改进了之前在 Fedora镜像(采用tini替代systemd) 的方案: 原先是直接在制作镜像时直接将公钥注入到镜像中,这个方法虽然简单但是比较笨拙(固化),所以我现在改为通过卷映射方式,将本地物理主机上的目录 home/
映射到容器内部:
可以灵活替换和修改密钥(也方便作为通用方案)
兼顾了用户目录数据持久化: 卷映射可以避免容器销毁后数据丢失,重建容器也可以保持数据。此外,如果多个容器共享一个映射目录,可以互相传递数据
按照 Docker tini进程管理器 经验总结,实现一个初始完备的远程可登录 Ubuntu Linux 系统:
ubuntu-ssh-tini
包含了安装 Docker tini进程管理器 以及 ssh服务 服务,但是和 Fedora镜像(采用tini替代systemd) 不同没有直接注入admin
的密钥:
FROM ubuntu:latest
MAINTAINER vincent huatai <vincent@huatai.me>
ENV container docker
RUN apt update -y
RUN apt upgrade -y
# 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 apt -y install sudo passwd openssh-client openssh-server curl
RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
# add account "admin" and give sudo privilege
RUN groupadd -g 505 admin
RUN useradd -g 505 -u 505 -d /home/admin admin
RUN adduser admin sudo
RUN echo "%sudo ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
# set TIMEZONE to Shanghai
RUN ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN mkdir /run/sshd
RUN ssh-keygen -A
# run service when container started - sshd
EXPOSE 22:1123
# Run your program under Tini
# CMD ["/your/program", "-and", "-its", "arguments"]
CMD ["/entrypoint.sh"]
备注
mkdir /run/sshd
是因为Ubuntu官方镜像是不提供ssh服务,缺少这个目录会导致sshd
启动失败,所以补充创建ssh-keygen -A
为sshd
运行创建主机密钥对没有如 Fedora镜像(采用tini替代systemd) 直接注入
admin
用户密钥,而是在docker run
是将物理主机用户目录bind到虚拟机内部提供卷,这样可以更灵活也保证了数据安全使用的
entrypoint.sh
脚本是 kind部署 fedora-dev-tini (tini替代systmed) 实践中改进过的脚本:
#!/usr/bin/env bash
sshd() {
chown -R admin:admin /home/admin
/usr/sbin/sshd
}
crond() {
/usr/sbin/cron
}
main() {
sshd
crond
# 在k8s不能直接bash执行结束,否则判断为pod Crash,需要改写成持续执行循环脚本
#/bin/bash
/bin/bash -c "while true; do (echo 'Hello from tini'; date; sleep 120); done"
}
main
备注
在运行
sshd
的函数中加了chown -R admin:admin /home/admin
是因为docker run
将物理主机home
目录映射到容器内部后,默认的属主是root
,这里为了能够使用普通用户账号admin
所以在容器初始化时候修订一次属主Ubuntu Linux 安装cron的包名字就是
cron
,安装后运行程序就是/usr/sbin/cron
,这个和 Fedora 不同如果在
docker
中运行最后执行的命令可以是/bin/bash
,但是为了能够在 ;ref:kubernetes 中通用最后必须是一个永续执行的程序,这里是循环,如果是应用容器则改为应用程序
构建
ubuntu-ssh-tini
镜像:
docker build --rm -t ubuntu-ssh-tini .
运行
ubuntu-ssh-tini
:
. ../../../etc/environment
docker run -dt --name ubuntu-ssh-tini --hostname ubuntu-ssh-tini \
-p 1123:22 \
-v ${BASE_DIR}/home:/home \
ubuntu-ssh-tini:latest
备注
这里运行docker容器的命令:
. ../../../etc/environment
是为了获取${BASE_DIR}
变量确定工作目录-v ${BASE_DIR}/home:/home
将物理主机的home目录映射到容器内部以便数据持久化
备注
除了docker容器以外, systemd-nspawn 也可以构建轻量级容器(类似chroot)
开发环境 ubuntu-dev-tini
¶
在 ubuntu-ssh-tini
基础上,增加开发工具包安装:
ubuntu-dev-tini
包含了安装常用工具和开发环境,并编译和安装必要的vim环境:
功能 |
参考 |
---|---|
docker容器运行ssh服务 |
|
用户目录ssh配置 |
|
ubuntu开发环境 |
构建
ubuntu-dev-tini
镜像:
运行
ubuntu-dev-tini
: