Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

vagrant + ansible + fabric でpythonの開発環境作る

More than 5 years have passed since last update.

vagrant + ansible + fabric でpythonの開発環境作る

  • vagrantで開発サーバ作って
  • そこにansibleでpython環境作る
  • flask + uwsgiを使用して
  • fabricでデプロイできるように

みたいな。

あんま突っ込んだ内容には触れてないです。

中途半端だけど、一通りまとまった情報がなかなか無くてけっこう時間費やしたので、
その辺のまとめておいてもいいかなって。
ハマりどころとかtips的に。

最終的なファイル構成はこんな感じ。

.
├── Vagrantfile
├── ansible.cfg
├── fabfile.py
├── flask
│   ├── main.py
│   ├── reload.trigger
│   ├── runserver.py
│   └── uwsgi.ini
├── inventory
├── playbooks
│   └── python.yml
└── ssh.config

vagrantで開発用のvmを作る

box追加

centos6 って名前でvagrantのboxを追加。

bash
vagrant box add centos6 http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-6.5_chef-provisionerless.box

設定

特に理由は無いけど2つ作ってみる。
rsyncでまとめてデプロイしてみたいし。

1個でよければ node1 だけでおk。

Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|

  config.vm.define :node1 do |node|
    node.vm.box = "centos6"
    node.vm.network :private_network, ip: "192.168.33.10"

    node.vm.provider :virtualbox do |vb|
        vb.customize ["modifyvm", :id, "--memory", "512"]
    end
  end

  config.vm.define :node2 do |node|
    node.vm.box = "centos6"
    node.vm.network :private_network, ip: "192.168.33.11"

    node.vm.provider :virtualbox do |vb|
        vb.customize ["modifyvm", :id, "--memory", "512"]
    end
  end

end

vmの ssh-config を用意

sshで繋ぐ時に便利なので。

bash
vagrant ssh-config > ssh.config

中身はこんな感じになるはず。

ssh.config
Host node1
  HostName 127.0.0.1
  User vagrant
  Port 2222
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile /Users/kuryu/.vagrant.d/insecure_private_key
  IdentitiesOnly yes
  LogLevel FATAL

Host node2
  HostName 127.0.0.1
  User vagrant
  Port 2200
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile /Users/kuryu/.vagrant.d/insecure_private_key
  IdentitiesOnly yes
  LogLevel FATAL

起動

bash
vagrant up

ansibleでpython環境作る

長くなるので記事分けた。
こっちを参照。
http://qiita.com/arc279/items/44ac688a2df24569f8af

インベントリはこんな感じ。

inventory
[servers]
node1
node2

↑の記事には書いてないけど、
ansible でsshする時にconfigを参照する設定を、ansibleの設定ファイルに書いておく。
ついでにインベントリファイルの指定も。

ansible.cfg
[defaults]
hostfile = inventory

[ssh_connection]
ssh_args = -F ssh.config

ansible.cfg はカレントに置いておけば勝手に読んでくれる。

実行はこう。

ansible-playbook playbooks/python.yml

flask + uwsgiを使用

本体

main.py
# -*- coding:utf-8 -*-

from flask import Flask

app = Flask(__name__)

@app.route("/")
def index():
    return "hello flask!!"

@app.route("/foo")
def foo():
    return "foo"

@app.route("/foo/bar")
def foo_bar():
    return "foobar"

Werkzeug 起動ファイル

runserver.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-

from main import app

options = {
    "debug": True,
    "threaded": True,
    "host": "0.0.0.0",
}
app.run(**options)

Werkzeugでデバッグ起動するならコレに実行権限付けて叩けばおk。

uwsgi 設定ファイル

touch-reload で、touchされたらuwsgiをリロードする用のファイルを指定。
必要なら daemonize の指定も入れるとよいと思う。

uwsgi.ini
[uwsgi]
socket = /tmp/flask.wsgi.sock
master = true
uid = vagrant
gid = vagrant
http = :5000
python-path = .      # uwsgi 起動ディレクトリがカレントになってる
wsgi = main:app
processes = 3
threads = 2
pidfile = ./flask.pid
touch-reload = ./reload.trigger
env = environment=development

なんかすごい不自然な書き方だけど、
ここで env = [key]=[value]の形で指定しておけば、
起動時に

import os
print os.environ["environment"]

で読める。

uwsgi 起動

↑でansibleでpyenv作った時に一緒にpipでuwsgiも入れてるはずなので、

flaskのカレントで

bash
uwsgi uwsgi.ini

で起動するはず。

fabric + rsync でデプロイ

rsyncは syncする側syncされる側 両方に入ってないと駄目。

↑のansibleの記事でrsyncも一緒に入れてるので、
ちゃんとplaybookが通ってればvm側にrsync入ってるはず。

ansibleのインベントリをfabricでも使用したい

詳細はこちらを参考に。
http://qiita.com/shivaken/items/c679ae9d15ac1cbebd0b

ssh-config を参照したい

こう。

env.use_ssh_config = True
env.ssh_config_path = "ssh.config"

ssh-config の指定で vagrantユーザで繋ぐようになってるので、
接続先の $HOME/home/vagrant になってる。

なので、

  • local_dir='./flask/',
    手元のflaskを

  • remote_dir='~/flask',
    vmの /home/vagrant/flask

rsync_project() でrysncする。

fabfile.py
from fabric.api import *
from fabric.decorators import roles
from fabric.contrib.project import rsync_project
import ansible.inventory

env.use_ssh_config = True
env.ssh_config_path = "ssh.config"

inventory = ansible.inventory.Inventory('inventory')
env.roledefs = inventory.groups_list()

def hostname():
    run("echo %s" % env.host)

def deploy():
    rsync_project(
        local_dir='./flask/',
        remote_dir='~/flask',
        exclude=['.DS_Tore', '*.tmp'],
        delete=True
    )
    reload()

@roles('servers')
def deployall():
    deploy()

def reload():
    run('touch ~/flask/reload.trigger')

fab

ロールを指定して

-R オプションでroleを指定。

ansibleのインベントリのグループ名がroleになってるらしい。
#この辺あまりちゃんと調べてない。

bash
fab -R servers deploy

@roles('servers') デコレータ付けてるこっちでもおk。

bash
fab deployall

単体ホスト名を指定して

bash
fab -H node1 deploy

なんかまとまりの無い内容になってしまった。

デプロイはrsyncじゃなくて git pull にするとか、
モダンなアレにしてもよいと思う。

もっとやるなら、

  • ansibleで一緒にnginx入れてuwsgiに繋ぐとか
  • uwsgi の start/stop もfabでできるようにするとか

いろいろあると思うけど、まぁその辺は開発環境作るってことでオミット。

arc279
フリーランスだけどわりとどこ行っても「いい感じにする」のに定評があるおっさん
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away