Small Docker Notes

From PaskvilWiki
Revision as of 11:11, 28 April 2016 by Admin (Talk | contribs)

Jump to: navigation, search

Note - vm and container is used below interchangeably.

Installation and Verification

  # install Docker
$ curl -fsSL https://get.docker.com/ | sh

  # add your-user to docker group to be able to run docker as non-root
$ usermod -aG docker your-user
  # you'll need to log out and in after this, or run all docker commands as root

  # verify the installation
$ docker run hello-world
  # this should download image from docker hub, and print "Hello from Docker." message

Stack in Separate Containers

Let's create few containers to hold different parts of the stack:

  • nginx
  • php-fpm
  • mysql
  • data volume for mysql
  • kyoto tycoon with python
  • data volume for kyoto tycoon

First, create config file for docker compose, called docker-compose.yml .

nginx:
    # based on latest nginx image
    image: nginx:latest
    ports:
        # map vm's port 80 to local port 8080
        - 8080:80

Now we have defined our first image, let's get it running:

$ docker-compose up -d

  # you should be able to reach the nginx on localhost:8080 now;
  # you can always check running containers, incl. ports map, with
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                           NAMES
e795e45c3e6b        nginx:latest        "nginx -g 'daemon off"   24 hours ago        Up 24 hours         443/tcp, 0.0.0.0:8080->80/tcp   dockertut_nginx_1

  # using container ID or name from `docker ps`, you can get lots of useful info with
$ docker inspect {container-id|name}

Adding php-fpm

Let's now add VM for php-fpm, and edit the docker-compose.yml like this:

nginx:
    build:
        # don't use image, build based on ./docker/nginx/Dockerfile
        ./docker/nginx/
    ports:
        # vm's port 80 will be available as 8080 on localhost
        - 8080:80
    links:
        # has access to 'php' vm
        - php
    volumes:
        # mount current directory as /var/www/html inside the container
        - .:/var/www/html

php:
    image: php:5.5-fpm
    expose:
        # expose port 9000 only to other vm's, not host machine like the 'ports' command
        - 9000
    volumes:
        - .:/var/www/html

Now the nginx image is based on Dockerfile in ./docker/nginx/ folder, which should look like this:

FROM nginx:latest
COPY ./default.conf /etc/nginx/conf.d/default.conf

This will build vm from nginx:latest image, and copy ./docker/nginx/default.conf to /etc/nginx/conf.d/ in the vm. Create this file with the following content:

server {
    listen 80 default_server;
    root /var/www/html;
    index index.html index.php;

    charset utf-8;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    access_log off;
    error_log  /var/log/nginx/error.log error;

    sendfile off;

    client_max_body_size 100m;

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_intercept_errors off;
        fastcgi_buffer_size 16k;
        fastcgi_buffers 4 16k;
    }

    location ~ /\.ht {
        deny all;
    }
}

Note that root /var/www/html; will actually use the mount of our local directory.

Also note fastcgi_pass php:9000; that uses the link created using links: key in the docker-compose.yml.

Now, let's just add index.php in the root folder (where docker-compose.yml resides):

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Hello World!</title>
    </head>
    <body>
        <?php echo "this is php!"; ?>                                                                                                                           
    </body>
</html>

Let's start the images; this time, php image should be pulled as well:

$ docker-compose up -d
Pulling php (php:5.5-fpm)...
5.5-fpm: Pulling from library/php
efd26ecc9548: Already exists                  <-- the nginx image, already pulled
a3ed95caeb02: Download complete
...

If you get "Service 'nginx' needs to be built, but --no-build was passed." message, run `docker-compose build` and `docker-compose up -d`. Verify all is OK and started:

docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                           NAMES
fd04b796e34f        dockertut_nginx     "nginx -g 'daemon off"   4 seconds ago       Up 4 seconds        443/tcp, 0.0.0.0:8080->80/tcp   dockertut_nginx_1
402fb35b762e        php:5.5-fpm         "php-fpm"                5 seconds ago       Up 4 seconds        9000/tcp                        dockertut_php_1

Note that nginx's image name has changed, since we have built a new one.

Now, when you open localhost:8080, you should get "this is php!" message. Open the index.php file, and edit it; the change should be immediately reflected. Sweet!

Data Volumes

Both the nginx and php vm's now use local folder through the volumes directive.

Better yet is to have a separate container; we'll build this container based on some image we're already using (to avoid having yet another image downloaded), but it won't be running - it'll just sit there, collecting data. Change docker-compose.yml like this:

nginx:
    build:
        ./docker/nginx/
    ports:
        - 8080:80
    links:
        - php
    volumes_from:
        - app

php:
    image: php:5.5-fpm
    expose:
        - 9000
    volumes_from:
        - app

app:
    # it's good practice to "reuse" some image, not to have yet another one pulled
    image: php:5.5-fpm
    volumes:
        - .:/var/www/html
    # container won't run - it'll execute `true` and sit there, collecting data
    command: "true"

Let's check all is OK:

$ docker-compose up -d
Creating dockertut_app_1...
Recreating dockertut_php_1...
Recreating dockertut_nginx_1...

  # list all containers (note that 'app' container is not listed in `ps`, since it's not running):
$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS                           NAMES
af0110364abf        dockertut_nginx     "nginx -g 'daemon off"   2 minutes ago       Up 2 minutes               443/tcp, 0.0.0.0:8080->80/tcp   dockertut_nginx_1
94a1c3d317dd        php:5.5-fpm         "php-fpm"                2 minutes ago       Up 2 minutes               9000/tcp                        dockertut_php_1
861cca283ceb        php:5.5-fpm         "true"                   2 minutes ago       Exited (0) 2 minutes ago                                   dockertut_app_1

and check that localhost:8080 is still responding.

TBC