Small Docker Notes
Note - vm and container is used below interchangeably.
Contents
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 .
# enter the following; this pulls latest nginx image, # and binds 8080 port on your machine to 80 port in the container
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