泥泞的沼泽 一个程序员的博客

How to configuration Nginx with bottle.py and uwsgi

Before you start, you should know how to install nginx and uwsgi, and have them already installed.

My ENV is using nginx 1.6.2, uwsgi 2.0.7 and Python 3.4.2

Add app.py for your bottle.py application

A simple application can be like below:

 1 from bottle import run, default_app
 2 
 3 @route('/')
 4 def home():
 5     return "I am running under nginx and uwsgi!"
 6 
 7 if __name__ == "__main__":
 8     run(host='0.0.0.0', port=8080)
 9 else:
10     application = default_app()

The key point of this piece of code is that have an application object once it’s imported. uwsgi will import load this file instead of running it.

uwsgi parameters

uwsgi can be ran like below:

uwsgi -s /var/run/uwsgi/app.sock -d /var/log/app/uwsgi.log -M --chdir /var/www/app

-s means you want to use a socket for uwsgi, -d means it runs in daemon mode, and --chdir tells uwsgi where is root of your application.

Nginx configuration

 1 server {
 2     listen 80;
 3     server_name domain.com;
 4     access_log /var/log/app/access.log;
 5     error_log /var/log/app/error.log;
 6     root /var/www/app;
 7 
 8     location / {
 9         include uwsgi_params;
10         uwsgi_pass unix:/var/run/uwsgi/app.sock;
11         uwsgi_param UWSGI_CHIDIR /var/www/app;
12         uwsgi_param UWSGI_SCRIPT app; # this is app.py with suffix
13     }
14 }

Once you start uwsgi and nginx, you will see your server running by visiting http://domain.com/!

How to build a boot2docker ISO with VirtualBox Guest Additions

In previous post, I talked about docker. But with boot2docker, there’s a big issue, that is you cannot mount local directories in container.

To understand this, we need to know how boot2docker works. As we know, docker only runs on Linux kernels. So boot2docker uses VirtualBox to create a Linux VM and then install docker in it. Thus, every docker command we run on Mac/Windows, actually runs in this VM. This Linux is tinycore linux, you can search more information for tinycore linux.

The problem is, this Linux VM doesn’t have VirtualBox Guest Additions(vga) installed. Without this, we cannot mount any local directories to VM. So our soluation is to install vga in tinycore linux.

Thanks to this Pull Request, we can build our own boot2docker.iso.

The basic idea of this is to pack vga drivers into tinycore linux before making an ISO.

Here’s the steps of building ISO:

  1. clone this repo: boot2docker
  2. patch this Pull Request
  3. docker build -t boot2docker . && docker run --rm boot2docker > boot2docker.iso
  4. backup ~/.boot2docker/boot2docker.iso and copy your iso here
  5. do the things listed here: https://github.com/boot2docker/boot2docker/pull/284#issue-29404515

There you go!

NOTICE: If you want to know the details of building an ISO, please refer to this: How to build boot2docker.iso locally

References

Create a MariaDB service on CentOS with Docker

Learning Docker for a long time, this is my first time to create a service with it. In Docker’s concept, each service should have a container, and your application may comes with many containers.

This time, I am gonna create a MariaDB service.

  1. First of all, let’s create a file named Dockerfile. Dockerfile is used to build an image:
    FROM centos:latest
    MAINTAINER David Xie "david.scriptfan@gmail.com"

    EXPOSE 3306
  1. With this file, we can get a clean CentOS image, but we don’t have MariaDB installed. MariaDB in CentOS’s repo is not the latest, we can install it from MariaDB’s official repo. This is easy, just create a repo file and put it /etc/yum.repos.d/. Our Dockerfile will look like this:
    FROM centos:latest
    MAINTAINER David Xie "david.scriptfan@gmail.com"

    ADD mariadb.repo /etc/yum.repos.d/mariadb.repo

    RUN yum install -y hostname MariaDB-server
    RUN yum clean all

    EXPOSE 3306

And `mariadb.repo`:

    [mariadb]
    name = MariaDB
    baseurl = http://yum.mariadb.org/10.0/centos6-amd64
    gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
    gpgcheck=1
  1. Now we have MariaDB installed, but how can I connect to it, and how to set password for root? Let’s add more files for it.
`server.cnf` is used to make sure we are not blocked by MariaDB:

    [mysqld]
    bind-address=0.0.0.0
    console=1
    general_log=1
    general_log_file=/dev/stdout
    log_error=/dev/stderr
    collation-server=utf8_unicode_ci
    character-set-server=utf8

`mariadb.sql` is used to update password for `root` to `root` and grant all privilliges to all IPs.

    USE mysql;
    GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
    FLUSH PRIVILEGES;
    UPDATE user SET password=PASSWORD("root") WHERE user='root';
    FLUSH PRIVILEGES;

`mariadb.sh` is used to apply all updates and start MariaDB service for us:

    #!/bin/sh
    chown -R mysql:mysql /var/lib/mysql
    mysql_install_db --user mysql > /dev/null

    mysqld_safe --user mysql &

    sleep 5s

    mysql -v < /root/mariadb.sql

    sleep 5s

    ps -wef | grep mysql | grep -v grep | awk '{print $2}' | xargs kill -9

    mysqld_safe --user mysql
  1. Final thing, we need to update our Dockerfile:
    # application container for MySQL
    # VERSION 2014-07-14

    FROM centos:latest
    MAINTAINER David Xie "david.scriptfan@gmail.com"

    ADD mariadb.repo /etc/yum.repos.d/mariadb.repo
    ADD mariadb.sql /root/mariadb.sql
    ADD server.cnf /etc/my.cnf.d/server.cnf
    ADD mariadb.sh /root/mariadb.sh

    RUN yum install -y hostname MariaDB-server
    RUN yum clean all
    RUN chmod +x /root/mariadb.sh

    EXPOSE 3306

    CMD ["/root/mariadb.sh"]
  1. We already have everything we need, we can create our container now.
    docker build --rm=true --no-cache=true -t mariadb .
    docker run -d -p 3306:3306 mariadb

After 10s, our container is ready to use. If you are using Docker on `boot2docker`, use `boot2docker ip` to get correct IP for it. Then you can connect your mariadb with `IP:3306`.

This project is on github, please visit: mariadb. If anything is wrong here, please let me know.

Rabbitmq and Pika

Install rabbitmq

It’s really easy to install rabbitmq on any linux distro.

  • CentOS You need to enable epel first, and then, run yum install -y rabbitmq-server

  • Fedora You don’t need to install epel to install rabbitmq, just run yum install -y rabbitmq-server

Run rabbitmq

After installing rabbitmq, you need to start rabbitmq service, which is also easy. Just type service rabbitmq-server start

Use pika to send message

When you have a rabbitmq environment, you can use pika to send and receive messages.

Send messages to rabbitmq using exchange

Create send.py with below code:

 1 import pika
 2 
 3 # create a connection for rabbitmq using localhost
 4 connection = pika.BlockingConnection(pika.ConnectionParameters(
 5                'localhost'))
 6 channel = connection.channel() # create a channel
 7 # declare an exchange
 8 channel.exchange_declare(exchange='messages', type='direct')
 9 # a routing is a label for a message
10 # receiver will decide which message to get according to routing
11 routings = ['info', 'warning', 'error']
12 
13 for routing in routings:
14     message = '%s message.' % routing
15     channel.basic_publish(exchange='messages',
16                           routing_key=routing,
17                           body=message)
18     print message
19 
20 connection.close()

Receive messages from rabbitmq

Create receive.py with below code:

 1 import pika
 2 
 3 connection = pika.BlockingConnection(pika.ConnectionParameters(
 4                'localhost'))
 5 channel = connection.channel()
 6 channel.exchange_declare(exchange='messages', type='direct')
 7 
 8 routings = ['info', 'warning', 'error']
 9 
10 # declare a queue to receive messages from exchange
11 # and bind queue to a routing_key
12 # this means, this queue can only receive message with this label
13 result = channel.queue_declare(exclusive=True)
14 queue_name = result.method.queue
15 for routing in routings:
16     channel.queue_bind(exchange='messages',
17                        queue=queue_name,
18                        routing_key=routing)
19 
20 def callback(ch, method, properties, body):
21     print " [x] Received %r" % (body,)
22 
23 channel.basic_consume(callback, queue=queue_name, no_ack=True)
24 
25 channel.start_consuming()

Run scripts

First, run send.py and then run receive.py. You can see results from console, to stop it, press ctrl-c

使用docker

什么是docker?

docker是一个Linux Container, 可以把OS运行在里面, 为用户提供一个隔离的, 虚拟的运行环境.

docker和virtualbox的区别就是, docker的container是构建在OS之上, 以进程的方式为用户提供服务, 而virtualbox提供的环境, 是一个完整的机器环境, 包括各种物理设备的虚拟, 像磁盘, 网络, USB等设备. 可以这么说, docker提供的container是一个比virtualbox更简单, 更便捷的容器, 在使用上, docker的速度也快于virtualbox.

安装docker

Docker刚刚release了它的1.0版本, 非常值得去体验啊.

安装docker其实非常简单, 根据自己的OS, 参照文档即可.

比如我是在Mac上装的docker, 使用的文档是: Installing Docker on Mac OS X

几个概念

container

可以理解为VM, 一个container就是一个VM.

image

创建container的镜像, 一般是一个OS的镜像, 里面除了放OS的东西, 还可以放各种application需要的东西, 比如程序代码, 数据等.

使用docker

在docker里创建contrainer, 需要一个可用的image, docker hub上有很多可用的image供大家使用, 比如说我是fedora的使用者, 我就可以用 docker pull fedora:heisenbug 来下载F20到本地. 下载成功后, 使用 docker images 来查看可用的images:

lxie@SanFrancisco ~ $ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
fedora-packager     heisenbug           8da72b37d6a4        9 hours ago         941.4 MB
fedora              heisenbug           3f2fed40e4b0        5 days ago          372.7 MB

有了image后, 你可以创建自己的container来运行你的application或者使用你的virtual os了: docker -t -i fedora:heisenbug /bin/bash, 怎么样? 已经在你的OS里了吧?

结论

本文只是介绍了如何安装docker, 并且使用已经创建好的image来建立自己的container, 这一步其实只是进入docker世界里最基本的一步, 后面我会继续介绍docker的命令和使用技巧.