Initially I wanted to write a detailed tutorial based on what I did a couple of months ago, but it turns out it’s no longer necessary. Docker Machine lets you configure your own server using a single command:
docker-machine create -d generic --generic-ip-address [ip] \
--generic-ssh-user [user] --generic-ssh-key ~/.ssh/[key] [name]
– [name]: how you’d like to call your server in Docker
– [ip]: public IP address of your server
– [user]: user login on your server
– [key]: user private key, for example id_rsa or a key file generated by your hosting service
You may also need to update your server’s firewall configuration by opening port 2376 for Docker daemon, along with any other ports the application is using (e.g. HTTP 80).
Now you can activate your server in Docker:
eval "$(docker-machine env [name])"
and you can run any docker image on it, for example nginx (adjust host port number as necessary):
docker run --name nginx1 -d -p 80:80 nginx
Now visit your server in a web browser and you should see familiar “Welcome to nginx!” page.
In my latest project I try to use the same application server in development and production environment (for simplicity, easier configuration, faster bugfixing, etc.) To achieve that I switched from embedded Flask / Werkzeug server in development and Apache mod_pyhon in production to embeddable, production-ready Waitress server.
One of the features I missed was automatically restarting the server whenever the code changes. I asked about this feature on Github and very helpful community members suggested various solutions, but none of the answers was satisfactory, so I decided to implement my own.
First I checked how other Python servers tackle this problem and all I came across work by spawning a monitor process (not thread!) with the same parameters as the main process, but with a special environment variable to distinguish between them. Examples:
* Werkzeug Reloader – code
* Pyramid pserve – code
This can be confusing for a programmer when the server is embedded inside the application, because any code before entering main event loop (updating database schema, opening a config file, displaying “Starting…” message, etc.) will be executed twice. It seems much cleaner to me to use a dedicated program that will monitor the server process and restart it when necessary.
I found some generic utilities that can do that (e.g. inotifywait, watchmedo trick), but none of them behaves exactly how I want, so I created reload.
It monitors current directory and subdirectories for any changes, ignoring paths specified in .reloadignore file as regular expressions. Perhaps I will add support for reading .gitignore and other files later.
In the end the implementation turned out pretty simple. reload is programming language and server independent and it can be used when developing with anything that restarts reasonably quickly.