Docker’s an ecosystem you have to immerse yourself into to make the most of it. But I can’t blame folks for wanting to just get in there and see what’s going on without all the reading and stuff…
I’ve put together what i call a “stumble through guide” for folks trying to get to grips with Docker, using Lucee server as an example. It’s a common approach to getting into Docker as described by the many questions I field from folks getting started. Most of all it’s a really great example of how you wouldn’t do development in this environment Still, stumbling about is often how we all learn things and with luck this will get you there quickly.
Make sure you have installed some form of Docker client and Docker engine.
$ docker -v
Docker version 17.04.0-ce, build 4845c56
And you know the Docker host IP. Might be localhost, might be an internal IP. Depending on your set up you may be able to tell like so.
$ docker-machine ip
192.168.99.100
Ok, lets just go for gold and spin up one of the official lucee docker images – Lucee 5 with NGINX.
$ docker run lucee/lucee51-nginx
Unable to find image 'lucee/lucee51-nginx:latest' locally
latest: Pulling from lucee/lucee51-nginx
693502eb7dfb: Already exists
...snip...8<... much gumph here ...snip...8<...
2017-04-22 00:34:24.398 loaded security
2017-04-22 00:34:24.399 loaded lib
22-Apr-2017 00:34:24.454 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-apr-8888"]
22-Apr-2017 00:34:24.459 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["ajp-apr-8009"]
22-Apr-2017 00:34:24.460 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 2990 ms
You’re going to get bored of that pretty quickly as it doesn’t do anything. You are looking at the STDOUT or console output of the Lucee servlet container. By default the container has no external ports nominated so nothing can talk to it.
CONTROL+C to kill the running container.
You need to nominate the container port and map it to an external port on the host. For example, NGINX port 80 inside the container to port 8080 on your desktop.
docker run -p 8080:80 lucee/lucee51-nginx
If all is going to plan you should be able to pull up the default page for the container at http://192.168.99.100:8080 <-- note your specific IP may be different.
Next you’re going to feel a burning desire to modify the code that makes up that page. A container is deliberately wrapped up and impenetrable, so we will need to punch “a little hole” in the container to let our changes through. This hole is called a volume and it’s a mapping between your desktop file system and a folder inside the container.
Let’s start with a real simple set up of a folder with a single index.cfm file containing <h1>hello world</h1>
.
Here’s an example. There’s no cut and paste option here; you will need to modify the file paths to follow your own desktop file structure.
$ mkdir -p /Users/modius/code/lucee-docker
$ cd /Users/modius/code/lucee-docker
$ echo “<h1>hello world</h1>” > index.cfm
$ docker run -p 8080:80 -v /Users/modius/code/lucee-docker:/var/www lucee/lucee51-nginx
Looking closely at the VOLUME:
-v /Users/modius/code/lucee-docker:/var/www
The first half is the location on your desktop:
/Users/modius/code/lucee-docker
The second half is the location within the container itself:
/var/www
Technically the volume is between the docker host file system and the container filesystem and the shared folder is between the host OS and the docker host but i digress. The VM layer will automatically sync file changes between these locations.
The files are in this location because the Lucee-NGINX Docker image has defined this as the location to store these files. Where you modify files within a container is going to vary from image to image. Note, this is one your first problems when trying to work out a standard across your team. If you have different directory set-ups, different operating environments — and you will — things get messy.
Almost immediately Lucee folks want to jump into the web administrator:
http://192.168.99.100:8080/lucee/admin/server.cfm
This is blocked by default in the official Lucee image; it’s a security precaution. In production Docker deployments you would never make modifications here. But for the sake of stumbling about, here’s how you would grant access to the admin.
In this Docker image (lucee/lucee51-nginx
) the admin is blocked by a directive in the NGINX config. You can easily override the default config with a simple replacement config that doesn’t block access.
Save default.conf
into your ./lucee-docker
folder:
server {
listen 80 default_server;
server_name _;
index index.cfm index.html index.htm;
root /var/www;
server_name_in_redirect off;
location ~* \.(cfm|cfc|cfr)$ {
proxy_pass http://127.0.0.1:8888;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_connect_timeout 600;
proxy_send_timeout 600;
proxy_read_timeout 600;
send_timeout 600;
}
}
And set up another VOLUME that maps that file over the top of the default configuration (again replacing for your own file paths):
docker run -p 8080:80 -v /Users/modius/code/lucee-docker:/var/www -v /Users/modius/code/lucee-docker:/etc/nginx/conf.d lucee/lucee51-nginx
Sort of awesome that it works but a limp, salad-fingers recipe for development.
The command line incantation caper gets old real quick; no one does Docker development like this. To get to grips with something more realistic install docker-compose and convert this docker cantrip into a working docker-compose.yml
file.
More on that later.