我想只使用Ansible的Playbook而不使用Dockerfile来创建容器镜像!
简要概括
使用Podman和Ansible Bender这两个工具,可以不使用Dockerfile来创建容器映像的方法如下所述。
有关Podman的具体内容,由于存在一些需要额外了解、配置的地方直至能够使用的坎坷经历,所以我也写了一些与主题不相关但似乎有必要了解的内容。
文章的背景
大约两年前,出于兴趣的一半开始使用Docker和Ansible创建容器。虽然我没有遵循标准方法,但经常以以下方式构建容器。
-
- (1) Dockerfileに以下の内容を記載
Ansibleをインストール
AnsibleのPlaybook関連ファイル一式をコンテナにコピー
ansible-playbookのコマンドを書いてイメージ構築
コンテナ起動時に実行するエントリーポイントのシェルスクリプト(entrypoint.shなどの名前のファイル)をコンテナにコピー
(2) Dockerイメージの作成
docker build …を実行
(3) Dockerコンテナを起動
docker run …を実行
エントリーポイントのシェルスクリプトの中で、ansible-playbookを実行
以下是以源代码表示的大致形象。(请原谅其中的不准确之处)
- Dockerイメージ作成時のソース
FROM ubuntu
# Ansibleをインストール
RUN apt -y update && \
apt -y install ansible
# AnsibleのPlaybook関連ファイル一式をコンテナにコピー
ADD ./playbook /
# ansible-playbookのコマンドを書いてイメージ構築
WORKDIR playbook
RUN ansible-playbook setup.yml
# エントリーポイントのシェルスクリプトをコンテナにコピー
WORKDIR /
ADD ./entrypoint.sh /
- コンテナ起動時のソース
#!/bin/bash
cd playbook
ansible-playbook entrypoint.yml
从源代码中可以看出,几乎只执行与Ansible相关的命令。 Dockerfile和入口点shell脚本entrypoint.sh是不可避的文件,用于创建Docker容器(尽管这样说有点不好),所以逐渐开始觉得不可避免地使用它们。并且越来越强烈地希望能够只使用Ansible而不使用Dockerfile和入口点shell脚本来创建Docker容器。
在Ansible容器中遇到的困难
在这样的思考中,我正在阅读有关Ansible的书籍时,偶然间得知了“在Ansible Container中只用Playbook就可以创建容器”的事实。我想:“这就是我一直在找的工具!我立刻开始安装并试用它!”于是我在搜索中设置开始了安装过程。
我反复遇到了两次三次的问题,直到最后终于成功地通过“ansible-container build”命令创建了Docker镜像。(由于描写Ansible Container的设置方法会偏离本文主题,所以这里省略了)
但是,当我试图实际构建镜像时,在执行了所有Playbook的步骤之后,最后出现了以下错误,导致无法创建镜像…。
docker.errors.APIError: 400 Client Error: Bad Request ("file with no instructions.")
在对此进行调查时,在海外的QA网站上找到了一条评论说“Ansible Container似乎已经不再推荐使用了”。在日本的网站上也有相关文章,明确表示应该使用“Ansible Bender”作为替代方案更好。
-
- Ansibleを使ってdockerコンテナを立ち上げる
https://note.com/tar28/n/n2479ab960187
尽管前言过长,但基于这样的经过,以下展示了使Ansible Bender可用的步骤。
步骤
-
- 主に参考にしたサイトは下記のAnsible Benderの公式サイト
https://ansible-community.github.io/ansible-bender/build/html/installation.html
根据官方网站的说明,为了运行Ansible Bender,需要安装Podman和Buildah。因此,首先我将介绍Podman和Buildah的安装方法,并提供一些推荐的设置配置。在本节的最后,将会介绍Ansible Bender的安装方法,请耐心等待。
(1) 安装Podman
Ansible Bender使用的不是Docker,而是一种新的容器构建工具,称为Podman。Podman几乎与Docker具有相同的用法,并且可以在无需守护程序(不需要启动服务)和无需Root权限的情况下构建镜像和容器。
以下网站上详细介绍了每个发行版的安装方法,按照说明可进行安装。
-
- Podman Installation Instructions
https://podman.io/getting-started/installation
(2) 安装 Buildah
Buildah和Podman一样,是一种无守护进程的工具,可用于创建容器镜像。(由于还没有完全理解,所以将根据需要进行补充。)安装方法详见以下网站。
-
- GitHubのBuildahのリポジトリ
https://github.com/containers/buildah/blob/master/install.md
(3) 有关Podman的设置
用户ID映射设置
如果想在用户权限下无根使用Podman(以及Ansible Bender),则需要进行称为“UID映射”的设置,具体如下。
$ sudo sh -c "printf \"\n$(whoami):100000:65536\n\" >>/etc/subuid"
进行此设置后,例如,Podman容器中的“root用户ID=0”将在主机操作系统(容器外部)中增加100000,并映射为“容器的root用户ID=100000”。因此,即使没有主机操作系统的root权限,也可以进行容器操作。
对于Podman镜像消耗大量存储空间的问题的解决方法
Podman的镜像和容器存储在主目录的~/.local/share/containers/storage/下。默认情况下,每次重新创建镜像时,镜像文件会被追加(而非差异化),导致占用大量存储空间的问题。(在我的环境中,最初构建镜像时存储空间不断减少,让我很焦虑…)
为解决此问题,可以安装适用于无根容器的存储驱动程序FUSE-OverlayFS,并将其应用于Podman的配置文件。
可以从以下网站安装FUSE-OverlayFS。
-
- GitHubのfuse-overlayfsのリポジトリ
https://github.com/containers/fuse-overlayfs
通过上述网站README中最后部分提到的下面的命令,可以生成fuse-overlayfs的二进制文件。
$ buildah bud -v $PWD:/build/fuse-overlayfs -t fuse-overlayfs -f ./Dockerfile.static.ubuntu .
安装后,只需在~/.config/containers/storage.conf中添加以下内容即可。之后,应该就不会再出现存储被耗尽的情况了。
[storage]
driver = "overlay"
[storage.options]
mount_program = "/usr/bin/fuse-overlayfs"
-
- この問題に関する参考サイト
コンテナ仮想、その裏側 〜user namespaceとrootlessコンテナ〜
(4) 安装 Ansible 和 Ansible Bender
终于可以解释 Ansible Bender 的安装方法了。
首先,要注意的是,Ansible Bender需要运行在Python3.6或更高版本上。因此,首先需要在Ansible控制节点上安装Python3.6或更高版本。
接下来,需要使用pip(3)命令在3.6或更高版本的Python环境中(可以是虚拟环境或非虚拟环境)安装Ansible和Ansible Bender。
$ pip3 install ansible
$ pip3 install ansible-bender
在上面的示例中,我们使用pip3命令来安装Ansible,但如果想要使用已经安装的Ansible,则可以在存放Playbook的yml文件的目录中创建ansible.cfg文件,并添加以下设置,这样就可以让Ansible引用Python3。
[defaults]
# python3のバイナリが格納されたパスを追加
interpreter_python=/usr/bin/python3
现在,准备工作已经完成,可以开始使用Ansible Bender了。
动作示例
暂时先随意创建一个空的目录
$ ansible-bender init
当输入命令时,将创建一个名为playbook.yml的模板文件。
如果按以下方式进行编辑,将能够创建一个基于CentOS7的httpd容器映像。
---
- name: Containerized version of httpd
hosts: all
vars:
ansible_bender:
base_image: centos:7
target_image:
cmd: /usr/sbin/httpd -D FOREGROUND
name: httpd
tasks:
- name: install dependencies needed to run project httpd
yum:
name: httpd
state: present
重点在于playbook的vars部分的变量ansible_bender。在这里,写下与要创建的容器相关的信息。可用的ansible_bender变量列表在ansible_bender下方的说明中列出。
-
- Anible BenderサイトのConfiguration
https://ansible-community.github.io/ansible-bender/build/html/configuration.html
以下是将上述playbook根据下列方式构建并创建Podman镜像的方法。
$ ansible-bender build playbook.yml
22:46:53.683 utils.py ERROR Getting image source signatures
22:46:54.479 utils.py ERROR Copying blob sha256:75f8…
(筆者の環境では幾つかエラーメッセージが出るが、原因は未解明)
PLAY [Containerized version of httpd] ******************************************
TASK [Gathering Facts] *********************************************************
ok: [httpd-20200814-224645662649-cont]
TASK [install dependencies needed to run project httpd] ************************
changed: [httpd-20200814-224645662649-cont]
PLAY RECAP *********************************************************************
httpd-20200814-224645662649-cont : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Getting image source signatures
Copying blob sha256:613b…
Copying blob sha256:7d45…
Copying config sha256:e05f…
Writing manifest to image destination
Storing signatures
e05f…
Image 'httpd' was built successfully \o/
确认 httpd 镜像是否已创建完成
$ podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/httpd latest e05f33470bcd 11 minutes ago 332 MB
启动容器
$ podman run --name httpd -p 10080:80 -dit httpd
请确认在 http://localhost:10080/ 上可以显示 Apache 的测试页面。
未解决的问题
在创建映像时,现在可以使用Ansible Playbook来编写Dockerfile!但目前还不清楚如何使用Ansible从目标节点执行容器启动时的入口点命令,将继续进行调查。