4
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

LimeSurvey の構築自動化(Dockerfile , ansible-container)

Last updated at Posted at 2018-02-27

LimeSurvey

OSSのWebアンケートシステム

多機能で見た目も素敵なので活用することにした。
いつものようにコンテナで使おうと思って、今回はDockerfileと久々にansible-containerで作ることにした。

結果として3つの自動化コードを作った。

  • Dockerfile
  • ansible-container 用 Role
  • Dockerfile からの ansible-container へマイグレーションした Role

いずれも、1,2回コマンド叩いてLimeSurveyが利用できるようになる。(コンテナイメージ作成、コンテナの起動)

動作環境

推奨の下記の環境で作ることにした。(Webに記載あり)

  • nginx 1.4.6
  • php 5.6.x
    • with php-fpm, mbstring, gd2 with freetype, imap, ldap, zip, zlib and databse drivers
  • mysql 5.5.50

実際に作った時の環境は以下

  • Docker : 17.12.0-ce
  • Base Image : CentOS 7.4.1708
  • Ansible : 2.4.2.0
  • Ansible-Container : 0.9.2
Package Version
nginx 1.13.9
php 5.6.33
Mariadb 5.5.56

Install Ansible and Ansible-Container

# yum install epel-release
# yum update

# yum install ansible
# yum install python-pip
# pip install --upgrade setuptools
# pip install ansible-container[docker,k8s]

1. Dockerfile

ソースはここ

下記のようなDockerfileを作成。

# Docker file for Lime Survey
FROM centos:7
MAINTAINER Tk

ARG URL=http://www.d-ip.jp/download/images/limesurvey2.73.0+171219_ja_dip.tar.gz

# Install Nginx
COPY nginx.repo /etc/yum.repos.d/
RUN yum -y update && yum -y install nginx

# Config Nginx for php
COPY default.conf /etc/nginx/conf.d/
 
# Install PHP 5.6
RUN yum -y install epel-release && yum -y update
RUN rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
RUN yum -y install --enablerepo=remi,remi-php56 php-fpm php-mbstring php-gd php-imap php-ldap php-zip php-zlib php-mysqlnd php-xml

# Config php-fpm 
RUN sed -i -e "s/^user\s=\sapache$/user = nginx/g" /etc/php-fpm.d/www.conf
RUN sed -i -e "s/^group\s=\sapache$/group = nginx/g" /etc/php-fpm.d/www.conf
RUN chgrp -R nginx /var/lib/php/{session,wsdlcache}

# Install Mariadb
RUN yum -y install mariadb-server

# Config Mariadb
RUN mysql_install_db --user=mysql --ldata=/var/lib/mysql/

# Download Limesurvey
RUN mkdir -p /var/www
RUN curl -L -o /tmp/limesurvey.tar.gz  ${URL}
RUN tar zxf /tmp/limesurvey.tar.gz -C /var/www &&  \
    mv /var/www/* /var/www/survey && \
    chown -R nginx.nginx /var/www/survey

# Set startup
COPY start.sh /root/
CMD ["/root/start.sh"]

補足

  • phpのパッケージはドキュメントに記載のなかったものを追加
  • nginx.repo 用意
  • default.conf 用意
  • mariadb,ngnix,php-fpmを順に起動するシェル準備(start.sh)
  • LimeSurveyインストーラで事前チェックで「セッション書き込み」にアラートが出たため、/var/lib/php/{session,wsdlcache}の属性変更

Build & Run

# docker build -t tksarah/limesurvey
Sending build context to Docker daemon  8.192kB
Step 1/19 : FROM centos:7
 ---> ff426288ea90

(略)
Successfully built af65374fe68f
Successfully tagged tksarah/limesurvey:latest

# docker run -id --name lime -p 80:80 tksarah/limesurvey

2. Ansible-Container Role

ソースはここ

# mkdir limesurvey
# cd limesurvey
# ansible-container init
Ansible Container initialized.

# ls
ansible-requirements.txt  ansible.cfg  container.yml  meta.yml  requirements.yml

# for x in limesurvey nginx mariadb php start; do ansible-galaxy init $x; done
- limesurvey was created successfully
- nginx was created successfully
- mariadb was created successfully
- php was created successfully
- start was created successfully

ロール作成

それぞれのロールを作る

limesurvey role

あまり美しくないが。。。Renameのところ。

defaults/main.yml
---
ROOT_DIR: /var/www
SERVICE_DIR: /var/www/survey
URL: "http://www.d-ip.jp/download/images/limesurvey2.73.0+171219_ja_dip.tar.gz"
tasks/main.yml
---
- name: Create Service Directory
  file: path={{ SERVICE_DIR }} owner=nginx group=nginx recurse=yes state=directory

- name: Download Limesurvey
  get_url: url={{ URL }} dest=/tmp/limesurvey.tar.gz

- name: Unarchive
  unarchive: src=/tmp/limesurvey.tar.gz dest={{ ROOT_DIR }} remote_src=yes

- name: Rename
  shell: mv {{ ROOT_DIR }}/*/* {{ SERVICE_DIR }}
  args:
    creates: "{{ SERVICE_DIR }}/index.php"

- name: Change attribute
  file: path={{ ROOT_DIR }} owner=nginx group=nginx recurse=yes state=directory

- name: Cleanup
  file: path=/tmp/limesurvey.tar.gz state=absent
vars/main.yml
---
URL: "https://github.com/LimeSurvey/LimeSurvey/archive/3.4.1+180221.tar.gz"

nginx role

  • templatesにdefault.conf.j2配置
defaults/main.yml
---
ROOT_DIR: "/var/www/survey"
SERVER_NAME: "localhost"
tasks/main.yml
- name: Add repository
  yum_repository:
    name: nginx
    description: Nginx Repo
    baseurl: http://nginx.org/packages/mainline/centos/7/$basearch/

- name: Install nginx
  yum: name=nginx state=latest disable_gpg_check=yes

- name: Config defalt.conf
  template: src=default.conf.j2 dest=/etc/nginx/conf.d/default.conf

mariadb role

tasks/main.yml
- name: Install Mariadb
  yum: name=mariadb-server state=latest disable_gpg_check=yes

- name: Initialize DB
  shell: mysql_install_db --user=mysql --ldata=/var/lib/mysql/ creates=/var/lib/mysql/mysql

php role

tasks/main.yml
- name: Install remi-release
  yum: name=http://rpms.famillecollet.com/enterprise/remi-release-7.rpm state=present disable_gpg_check=yes
- name: Install epel-release
  yum: name=epel-release state=latest disable_gpg_check=yes

- name: Install PHP 5.6
  yum: name={{ item }} state=latest enablerepo=remi,remi-php56 disable_gpg_check=yes
  with_items:
    - php-fpm
    - php-mbstring
    - php-gd 
    - php-imap
    - php-ldap
    - php-zip
    - php-zlib
    - php-mysqlnd
    - php-xml

- name: Config php-fpm for user
  lineinfile: path=/etc/php-fpm.d/www.conf regexp='^user\s=\sapache$' line='user = nginx'

- name: Config php-fpm for group
  lineinfile: path=/etc/php-fpm.d/www.conf regexp='^group\s=\sapache$' line='group = nginx'

- name: Change attribute
  file: path='/var/lib/php/{{ item }}' group=nginx
  with_items:
    - session
    - wsdlcache

start role

  • files/start.sh 配置
tasks:main.yml
- name: Copy Start script
  copy: src=start.sh dest=/root/start.sh mode=755 owner=root group=root

container.yml の作成

version: "2"
settings:
  conductor:
    base: centos:7

  project_name: lime

services:
  limesurvey:
    from: "centos:7"
    roles:
      - nginx
      - php
      - mariadb
      - limesurvey
      - start
    ports:
      - "80:80"
    command: ["/root/start.sh"]
    dev_overrides:
      environment:
        - "DEBUG=2"

registries: {}

Build & Run

# ansible-container build
Building Docker Engine context...
Starting Docker build of Ansible Container Conductor image (please be patient)...
Parsing conductor CLI args.
Docker? daemon integration engine loaded. Build starting.      project=lime
Building service...     project=lime service=limesurvey

PLAY [limesurvey] **************************************************************

(略)

PLAY RECAP *********************************************************************
limesurvey                 : ok=2    changed=1    unreachable=0    failed=0

Applied role to service role=start service=limesurvey
Committed layer as image        image=sha256:3bc525a274f0f200f3d6deec0d2c952c1b18b423347b6f3062629ab3c17f595d service=limesurvey
Build complete. service=limesurvey
All images successfully built.
Conductor terminated. Cleaning up.      command_rc=0 conductor_id=7e6027e26a72a147c15901f32c68ca9cf94b554ac900c547a367b250fc290461 save_container=False


# # ansible-container run
Parsing conductor CLI args.
Engine integration loaded. Preparing run.       engine=Docker? daemon
Verifying service image service=limesurvey

PLAY [Deploy lime] *************************************************************

TASK [docker_service] **********************************************************
changed: [localhost]

PLAY RECAP *********************************************************************
localhost                  : ok=1    changed=1    unreachable=0    failed=0

All services running.   playbook_rc=0
Conductor terminated. Cleaning up.      command_rc=0 conductor_id=a47da5e993a652782418978a5538588838501accdaab88690e27bb9b8ccd75a5 save_container=False


# docker ps
WARNING: Error loading config file: /root/.docker/config.json - read /root/.docker/config.json: is a directory
CONTAINER ID        IMAGE                            COMMAND             CREATED              STATUS              PORTS                NAMES
87342d1aa3c7        lime-limesurvey:20180227140838   "/root/start.sh"    About a minute ago   Up About a minute   0.0.0.0:80->80/tcp   lime_limesurvey_1

run した後にもう一回 run しても冪等性が保たれる。

# ansible-container run
Parsing conductor CLI args.
Engine integration loaded. Preparing run.       engine=Docker? daemon
Verifying service image service=limesurvey

PLAY [Deploy lime] *************************************************************

TASK [docker_service] **********************************************************
ok: [localhost]

PLAY RECAP *********************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0

All services running.   playbook_rc=0
Conductor terminated. Cleaning up.      command_rc=0 conductor_id=78904d7a5422cc6e51f5fe9e21bd5120d461178274b97c05032776acada59009 save_container=False
[root@kujira limesurvey]# docker ps -a
WARNING: Error loading config file: /root/.docker/config.json - read /root/.docker/config.json: is a directory
CONTAINER ID        IMAGE                            COMMAND             CREATED              STATUS              PORTS                NAMES
87342d1aa3c7        lime-limesurvey:20180227140838   "/root/start.sh"    About a minute ago   Up About a minute   0.0.0.0:80->80/tcp   lime_limesurvey_1

ansible-container の他オプション、stop で停止、restart で再起動、destroyでコンテナの削除

トラブル

ansible-cintainer build 実行時のエラー

ansible-container build fails with AttributeError: 'tuple' object has no attribute 'id'

原因

pip バージョン依存によるエラー
https://github.com/ansible/ansible-container/issues/884

ワークアラウンド

python docker モジュールのダウングレード

# pip show docker
---
Metadata-Version: 2.0
Name: docker
Version: 3.1.0

# pip install -U docker==2.7.0

ansible-container 実行後のワーニング

docker コマンド実行時に毎回出て来る。

# docker ps
WARNING: Error loading config file: /root/.docker/config.json - read /root/.docker/config.json: is a directory
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

原因

解決済み(0.9.3 Fixバージョン)
今回使ってるのは0.9.2なので、アップグレードをまつことにする。

ワークアラウンド

  • 無視
  • ansible-container build 後に削除 .docker/config.json を削除

3.(おまけ)Migrating from a Dockerfile

ansible-container には Dockerfile からのマイグレーション機能が付いている。

これを使って見たところ下記のような出力と共に YAML ファイルが生成された。

# mkdir migrate_dir
# cd migrate_dir/
# ansible-container import ../dockerfile/limesurvey # ・・・この配下にDockerfileが存在
Project successfully imported. You can find the results in:
/root/migrate_dir
A brief description of what you will find...


container.yml
-------------

The container.yml file is your orchestration file that expresses what services you have and how to build/run them.

settings:
  conductor_base: centos:7
services:
  limesurvey:
    roles:
    - limesurvey


I added a single service named limesurvey for your imported Dockerfile.
As you can see, I made an Ansible role for your service, which you can find in:
/root/migrate_dir/roles/limesurvey

migrate_dir/roles/limesurvey/tasks/main.yml
-------------------------------------------

The tasks/main.yml file has your RUN/ADD/COPY instructions.

- name: Ensure /etc/yum.repos.d/ exists
  file:
    path: /etc/yum.repos.d/
    state: directory
- name: Install Nginx (nginx.repo)
  copy:
    src: nginx.repo
    dest: /etc/yum.repos.d/
- shell: yum -y update && yum -y install nginx
- name: Ensure /etc/nginx/conf.d/ exists
  file:
    path: /etc/nginx/conf.d/
    state: directory
- name: Config Nginx for php (default.conf)
  copy:
    src: default.conf
    dest: /etc/nginx/conf.d/
- name: Install PHP 5.6
  shell: yum -y install epel-release && yum -y update
- shell: rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
- shell: yum -y install --enablerepo=remi,remi-php56 php-fpm php-mbstring php-gd php-imap
    php-ldap php-zip php-zlib php-mysqlnd php-xml
- name: Config php-fpm
  shell: sed -i -e "s/^user\s=\sapache$/user = nginx/g" /etc/php-fpm.d/www.conf
- shell: sed -i -e "s/^group\s=\sapache$/group = nginx/g" /etc/php-fpm.d/www.conf
- shell: chgrp -R nginx /var/lib/php/{session,wsdlcache}
- name: Install Mariadb
  shell: yum -y install mariadb-server
- name: Config Mariadb
  shell: mysql_install_db --user=mysql --ldata=/var/lib/mysql/
- name: Download Limesurvey
  shell: mkdir -p /var/www
- shell: curl -L -o /tmp/limesurvey.tar.gz  ${URL}
- shell: tar zxf /tmp/limesurvey.tar.gz -C /var/www
- shell: mv /var/www/* /var/www/survey
- shell: chown -R nginx.nginx /var/www/survey
- name: Ensure /root/ exists
  file:
    path: /root/
    state: directory
- name: Set startup (start.sh)
  copy:
    src: start.sh
    dest: /root/


I tried to preserve comments as task names, but you probably want to make
sure each task has a human readable name.

migrate_dir/roles/limesurvey/meta/container.yml
-----------------------------------------------

Metadata from your Dockerfile went into meta/container.yml in your role.
These will be used as build/run defaults for your role.

# Docker file for Lime Survey
from: centos:7
maintainer: Tk
command:
- /root/start.sh


I also stored ARG directives in the role's defaults/main.yml which will used as
variables by Ansible in your build and run operations.

Good luck!
Project imported.
  • コメント「#」は -name に置き換わっている
  • shell , copy などのモジュール中心に置き換わっている

でもって、できたもので試しにビルドしてみる

# ansible-container build

結果はエラー。
ただ、よく見たら変数指定がおかしくなっているところがあり、そこを直して再実行したら通った。

- shell: curl -L -o /tmp/limesurvey.tar.gz  ${URL}
=>
- shell: curl -L -o /tmp/limesurvey.tar.gz  {{ URL }}

さっそく、run してみる。

# ansible-container run
Parsing conductor CLI args.
Engine integration loaded. Preparing run.       engine=Docker? daemon
Verifying service image service=limesurvey

PLAY [Deploy migrate_dir] ******************************************************

TASK [docker_service] **********************************************************
fatal: [localhost]: FAILED! => {"changed": false, "errors": ["ERROR: for migratedir_limesurvey_1  Cannot start service limesurvey: OCI runtime create failed: container_linux.go:296: starting container process caused \"exec: \\\"/root/start.sh\\\": permission denied\": unknown", "ERROR: for limesurvey  Cannot start service limesurvey: OCI runtime create failed: container_linux.go:296: starting container process caused \"exec: \\\"/root/start.sh\\\": permission denied\": unknown"], "failed": true, "module_stderr": "Creating migratedir_limesurvey_1 ... \r\n\r\u001b[1B\nERROR: for migratedir_limesurvey_1  Cannot start service limesurvey: OCI runtime create failed: container_linux.go:296: starting container process caused \"exec: \\\"/root/start.sh\\\": permission denied\": unknown\n\nERROR: for limesurvey  Cannot start service limesurvey: OCI runtime create failed: container_linux.go:296: starting container process caused \"exec: \\\"/root/start.sh\\\": permission denied\": unknown\n", "module_stdout": "", "msg": "Error starting project ERROR: for limesurvey  Cannot start service limesurvey: OCI runtime create failed: container_linux.go:296: starting container process caused \"exec: \\\"/root/start.sh\\\": permission denied\": unknown"}
        to retry, use: --limit @/root/migrate_dir/ansible-deployment/playbook.retry

PLAY RECAP *********************************************************************
localhost                  : ok=0    changed=0    unreachable=0    failed=1

Traceback (most recent call last):
  File "/usr/bin/conductor", line 11, in <module>
    load_entry_point('ansible-container', 'console_scripts', 'conductor')()
  File "/_ansible/container/__init__.py", line 19, in __wrapped__
    return fn(*args, **kwargs)
  File "/_ansible/container/cli.py", line 399, in conductor_commandline
    **params)
  File "/_ansible/container/__init__.py", line 19, in __wrapped__
    return fn(*args, **kwargs)
  File "/_ansible/container/core.py", line 854, in conductorcmd_run
    'Error executing the run command. Not all containers may be running.'
container.exceptions.AnsibleContainerException: Error executing the run command. Not all containers may be running.
Conductor terminated. Cleaning up.      command_rc=1 conductor_id=467076af06bebe4167568c5fbe21967158517991128d09b4aefce1a0cfdf9902 save_container=False
ERROR   Conductor exited with status 1

/root/start.sh の実行属性がとれてしまってるので、下記のようにつけたら run も成功。

migrate_dir/roles/limesurvey/tasks/main.yml
# 最後の copy task
- name: Set startup (start.sh)
  copy:
    src: start.sh
    dest: /root/
    mode: 0755

ただし、ansible-container run は成功したものの、 Port 部分がアクティブにならなかった。
理由は、Dockerfile に「EXPOSE 80:80」を記載していないため。これをDockerfileに追記し、import することで run も問題なく成功。
なお、この port の設定は下記のファイルに格納されていた。(ansible-container import 実行時の出力にも表示されている)

/migrate_dir/roles/limesurvey/meta/container.yml
# Docker file for Lime Survey
from: centos:7
maintainer: Tk
ports:
- 80:80
command:
- /root/start.sh

おまけの、まとめ

ansible-container import のマイグレーションの留意点(version 0.9.2 時点)。

  • 変数の確認
  • 配布された実行権限付与ファイルの確認
  • Dockerfile のパラメータ確認(EXPOSE等)

ansible-container の所感

  • まだ1.xになっていないこともあり、若干のBugや留意点が存在
  • Dockerfile からのマイグレーションはかなり雑だと思いきや、結構使える(上記、留意点込)
  • 他のオーケストレーションへのデプロイも対応しているため、期待できる(今回はそこまでは未確認)
4
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?