Murky Swamp coding life!

Kill containers in Docker

After using Docker for a while, you may find out there are so many containers in stopped status, and they are not deleted. You can delete them one by one with docker rm, but we are developers, how can we bear this?

Thank god Docker provides a parameter named -q in docker ps command to just print container IDs on console.

  • Delete all stopped containers

    docker rm $(docker ps -f status=stopped -q)

  • Delete all containers

    docker rm -f $(docker ps -a -q)

Isn’t it cool? If not, make some alias for this, like alias drma=docker rm -f $(docker ps -a -q), that’s how it’s done!

Return text with Nginx

There is always a time that you want your web server just return some plain text to user or monitor services. One way of doing it is to create a static file and use url of this file.

Is there a better way for this?

Nginx allows user use ‘return’ to return a HTTP code and some text, which is perfect for us.

Here’s a simple example:

1 server {
2     listen 8080;
3     location /index.html {
4         return 200 "ok";
5     }
6 }

As we can see, return accepts 2 arguments, first one is HTTP Code, and last one is text you want to show. For HTTP Code, you can use 200, 204, 400, 402-406, 408, 410, 411, 413, 416 , 500-504

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
    
  2. 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
    
  3. 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
    
  4. 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"]
    
  5. 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.