容器配置開發環境小計

  • 2020 年 2 月 14 日
  • 筆記

前言

這段時間折騰了好久容器搭建開發環境和家裡軟路由趟的一些坑。這裡先記錄一下使用容器搭開發環境的一些流程和問題。

開發環境一般裏面會包含很多的工具和開啟一些服務。 我自己的環境測試和搭建了 ubuntucentosarchlinux 。 開啟了 systemd , 支持網絡代理+vscode遠程開發, 支持 dockerpodman ,支持k8s,開啟了 sshd 。 所有的構建腳本及 Dockerfile 都放在 https://github.com/owent-utils/docker-setup 了,有需要的小夥伴可以自取。

編譯podman

之前看一些文章把 podman 吹上了天,於是我就當了下小白鼠。最後的建議是除非你想去折騰這玩意,不然現階段還是珍愛生命,遠離它(BUG茫茫多,想想都是淚)。

除了一些自帶的發行版以外,有些發行版(比如 Debian)還是得自己編譯自己裝。發行版自帶的版本也相對較低,如果想用比較新的版本也是得自己編譯安裝。 官方給出的編譯安裝組件並不完整,而且 podman 內部的一些組件互相依賴的版本也很高,系統自帶的組件版本也不一定能夠支持,我自己總結的需要準備的列表如下:

  1. golang
  2. ostree
  3. conmon(容器監控工具)
  4. runc(容器運行工具)
  5. cni(對非host模式rootful容器的網絡支持)
  6. libpod(podman 命令行工具)
  7. fuse-overlayfs(rootless容器的用戶空間文件系統掛載支持)
  8. slirp4netns(rootless容器的用網絡支持)

具體的流程在: https://github.com/owent-utils/docker-setup/blob/master/build-podman.sh

基本設置

拉取鏡像和網絡代理和自建鏡像倉庫

拉取 docker 鏡像的命令我就不貼了。這裡如果是用的docker 而不是 podman 並且網絡要要走代理需要配置下。

首先 docker 服務的代理只能配環境變量,需要在 /lib/systemd/system/docker.service 里(假設用的 systemd 啟動的 docker 服務)的 [Service] 段里加上

Environment="HTTP_PROXY=HTTP代理地址:端口" "HTTPS_PROXY=HTTP代理地址:端口" "NO_PROXY=代理排除列表"

然後如果有自定義鏡像倉庫要排除TLS證書檢查的話可以在 /etc/docker/daemon.json 里配置:

{      "graph": "數據存放路徑,如: /data/docker-data",      "storage-driver": "overlay",      "insecure-registries" : [ "registry.fedoraproject.org", "registry.access.redhat.com", "registry.centos.org", "docker.io", "quay.io", "其他自建倉庫..." ]  }

鏡像構建流程

  1. 換源
  2. 很多容器官方鏡像是關閉文檔的,開發環境還是需要它所以打開文檔安裝man-db
  3. 開文檔後可能要重新安裝某些組件觸發一次拉取文檔和man-db
  4. 安裝基本工具
  5. 安裝編譯環境
  6. 生成locale,某些發行版沒有 locale.gen , 直接執行 localectl set-locale LANG=en_GB.utf8
  7. 設置時區
  8. 開啟sshd服務,改服務端口,把 /etc/pam.d/* 里的 pam_loginuid.so 改成 optional 。
  9. 清理安裝包緩存目錄和日誌

大致就是如上的流程,這裡提供一下我自己構建過的幾個 Dockerfile , 都在 https://github.com/owent-utils/docker-setup 這個倉庫里,部分Dockerfile可能會依賴裏面的腳本所以最好整個倉庫clone下來就可以直接用。如果要設置開發環境代理的話可以在構建鏡像的時候加上 --env SETUP_INSTALL_PROXY=HTTP代理地址--env SETUP_INSTALL_NO_PROXY=代理排除地址

在宿主機上測試( 兼容systemd )

要讓容器能夠啟動 systemd 的話需要額外給一些權限和共享出cgroup。 然後啟動命令必須是 /lib/systemd/systemd

我試了幾個主要的發行版都是 /lib/systemd/systemd ,有些發行版會安裝 systemd 適配 sysv 的包,然後 /sbin/init 會被軟鏈到 /lib/systemd/systemd ,用這個也可以。 如果是 podman 的話內建了對 systemd 的支持。只要加上啟動參數 --systemd true 就可以了。 如果是原版的 docker 的話,這裡提供一個命令參考(參數選項來自 podman 的代碼): docker run -d –name 容器名稱 –cap-add=SYS_ADMIN –mount type=tmpfs,target=/run,tmpfs-mode=1777,tmpfs-size=67108864 –mount type=tmpfs,target=/run/lock,tmpfs-mode=1777,tmpfs-size=67108864 –mount type=tmpfs,target=/tmp,tmpfs-mode=1777 –mount type=tmpfs,target=/var/log/journal,tmpfs-mode=1777 –mount type=bind,source=/sys/fs/cgroup,target=/sys/fs/cgroup 鏡像HASH值或TAG名稱 /sbin/init

網絡代理和vscode和zsh

我現在主力使用vscode 遠程開發插件來遠程開發的。但是配置容器網絡的時候碰到過很多問題,要麼某些環境初始化不了,要麼更新失敗。

我試過加初始化代理的環境變量腳本到 $HOME/.bashrc 和加到 /etc/profile.d/xxx.sh 都不能完美解決問題。特別是使用了 zsh 之後。

最終比較完美的解決方案有兩種,第一種是把代理環境變量寫進 Dockerfile 里, 另一種是 sshd 的配置( /etc/ssh/sshd_config ) 里開啟 PermitUserEnvironment yes 然後把環境變量寫進 $HOME/.ssh/environment 里。(記得要 chmod 600 $HOME/.ssh/environment

其他

這段時間還折騰了下 nftables ,用起來很爽,但是也是踩了一些坑。不過這個組件比 podman 靠譜多了,只是功能上還不能完全替代 iptables + ebtables 而已。 我也是嘗試用了好多種發行版docker里跑軟路由,後面再來填坑吧。