背景
Dockerコンテナ内にAnsibleをインストールしてみた、Ansibleを使ってDockerをインストールしてみたと言ったブログ記事は、いくつかありましたが、AnsibleのPlaybookを使ってDockerコンテナを構築する記事がまだ少なく感じましたので、今回はAnsibleを実行して、Vue.jsのフレームワークであるNuxt.jsのDockerコンテナを構築してみた結果を記事として残します。
実施すること
下記の内容をAnsibleのPlaybookから実行できるようにします。
- Dockerイメージ取得
- Nuxt.jsコンテナを構築
- Docker Hubへのイメージpush
因みに構築予定のNuxt.jsコンテナのビルド元のDockerFileはこちらの技術書を参考にしました。
試して学ぶ Dockerコンテナ開発
各種ツール
- Ansible 2.9.10
- Docker 19.03.11
- Docker API 1.40
- Python 3.8.2
- Docker SDK Python 1.80
使うAnsibleのモジュールですが、docker_imageとdocker_containerを使用します。
これらのモジュールは、Docker APIのバージョンが1.20以上、Docker SDK Pythonのバージョンが1.80以上という必要条件がありますので、事前にバージョンを上げておきます。また必須ではありませんが、docker_imageモジュールのいくつかのオプションはAnsibleのバージョンが2.8以上でなければ動作しないものがいくつかありますので、できればAnsibleのバージョンも上げておきます。
事前準備
まず初めに、Nodeイメージを取得し、簡単にNuxt.jsのプロジェクト構築ができるツールcreate-nuxt-appを事前に使用してappディレクトリをホームディレクトリとするDockerfileを作成します。
FROM node:latest
WORKDIR /app
このDockerfileをビルドして、Nodeコンテナ作成後、アタッチしNuxt.jsプロジェクトのひな型を構築します。
docker run --rm -it <コンテナID> bash
yarn create nuxt-app
(コンテナ内)
実行しますと対話形式で設定方法が聞かれますので、好みに合わせてカスタマイズしていきます。
ひな型の作成が完了しましたら、新しくターミナルを開いてローカルマシン上へ作成したひな型をコピーします。
docker cp <コンテナID>:/app .
これで準備は整いましたので、DockerfileとPlaybookを作成していきます。
ディレクトリ構成
ディレクトリ構成は以下の通りです。
$ tree
├── dockerFile
│ ├── Dockerfile
│ └── app/(Nuxt.jsのひな型)
└── build_image.yml
└── create_container.yml
DockerFile作成
Nodeコンテナから持ってきたローカル上のNuxt.jsひな型をNuxt.js用のコンテナへ配置してNuxt.jsが構築されるDockerfileを作成します。
FROM node:latest
ENV NUXT_HOST=0.0.0.0
ENV NUXT_TELEMETRY_DISABLED=1
WORKDIR /app
COPY ./app/package.json ./app/yarn.lock ./
RUN yarn install
COPY ./app .
CMD ["yarn", "run", "dev"]
Playbook作成
次にNuxt.jsのコンテナイメージをビルドするためのPlaybookを作成します。
- name: Build Nuxt.js image
hosts: localhost
tasks:
- name: build nuxt.js
docker_image:
build:
path: ./dockerFile
name: yuta28/ansible-test
tag: Nuxtimage
push: yes #イメージビルド後自動的にDockerHubへpushする
source: build
register: build_result
- debug: var=build_result
docker_image内のbuildオプションでDockerfileのパスを指定しています。nameオプションは出来上がったDockerイメージの名前を付けています。yuta28は私のDocker Hubのアカウント名であり、Docker Hubへpushする場合イメージ名をDocker Hubアカウント/リポジトリ名と名付ける必要があるためこのような名前にしました。最後のsourceオプションでbuildを指定することで、DockerFileからイメージをビルドするようにしています。
最後に、イメージを基にコンテナを作成するためのPlaybook、create_container.ymlを作成致します。
- name: Create and buid container
hosts: localhost
tasks:
- name: Nuxt container
docker_container:
name: NuxtContaier
image: yuta28/ansible-test:Nuxtimage
state: started
ports:
- "127.0.0.1:8080:3000" #コンテナ内のポート3000にNuxt.jsが構築されるのでローカルのポート8080から参照できるようにマッピング
tty: true
detach: true
register: contaier_result
- debug: var=contaier_result
Ansible実行
実行するための準備が完了しましたので、Ansibleを実行します。
$ ansible-playbook build_image.yml
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
PLAY [Build Nuxt.js image] ***************************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************
ok: [localhost]
TASK [build nuxt.js] *********************************************************************************************************************************************************************************
[WARNING]: The default for build.pull is currently 'yes', but will be changed to 'no' in Ansible 2.12. Please set build.pull explicitly to the value you need.
changed: [localhost]
TASK [debug] *****************************************************************************************************************************************************************************************
ok: [localhost] => {
"build_result": {
"actions": [
"Built image yuta28/ansible-test:Nuxtimage from ./dockerFile",
"Pushed image yuta28/ansible-test to docker.io/yuta28/ansible-test:Nuxtimage"
],
~~~~~~~~~~~~~~~~~~~省略~~~~~~~~~~~~~~~~~~~~
"warnings": [
"The default for build.pull is currently 'yes', but will be changed to 'no' in Ansible 2.12. Please set build.pull explicitly to the value you need."
]
}
}
PLAY RECAP *******************************************************************************************************************************************************************************************
localhost : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
$ ansible-playbook create_container.yml
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
PLAY [Create and buid container] *********************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************************************
ok: [localhost]
TASK [Nuxt container] ********************************************************************************************************************************************************************************
changed: [localhost]
TASK [debug] *****************************************************************************************************************************************************************************************
ok: [localhost] => {
"contaier_result": {
"ansible_facts": {
"docker_container": {
"AppArmorProfile": "docker-default",
"Args": [
"yarn",
"run",
"dev"
],
~~~~~~~~~~~~~~~~~~~省略~~~~~~~~~~~~~~~~~~~~
}
}
PLAY RECAP *******************************************************************************************************************************************************************************************
localhost : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
無事にコンテナの作成まで完了しました。
docker ps
でコンテナが起動しているか確認して、Nuxt.jsのサンプルページにアクセスできるか試してみます。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f5597614f5d5 yuta28/ansible-test:Nuxtimage "docker-entrypoint.s…" 37 minutes ago Up 37 minutes 127.0.0.1:8080->3000/tcp NuxtContaier
問題なくNuxt.jsのサンプルページにアクセスすることができました。
Docker Hubへのpush
build_image.yml
の中身に含まれているオプションpush:yes
でログイン済みのDocker Hubにイメージをpushすることができます。
所感
Dockerのイメージ取得、ビルド、コンテナ作成、起動、DockerHubへのpushをAnsibleを使って一通り行うことができました。ただ、最初に事前準備のnuxt-appは対話形式での設定方法のため予めDockerfileにコマンドを書いてもその後の設定が行えず、いい方法も思いつかないため直接コンテナ内に入って手動でnuxt-appを実行しました。
実は2,3年くらい前の技術書やWebサイトにはAnsible Containerというコンテナの構築やビルドに便利なツールがありました。
ですが、2020年現在は開発が終了したのか非推奨になっております。(pip install ansible-container
しても見つかりませんでした)
Ansibleには、Docker関連に特化したモジュールが豊富に用意されており、今回使用した2つのモジュール以外にも多くのモジュールがありますので、気になる方はリファレンスマニュアルを覗いてみてください。