Linux Format

Docker Archiving servers............

Jonni Bidwell finds Docker containers running tasty Nginx containers much more preferable to the cordial discussion at tupperware parties…

-

Jonni Bidwell uses the container tech to mothball an ancient forum for safe keeping.

We’ve covered setting up webservers like Apache (see LXF197) and Nginx (pronounced engine-x, see LXF222) before. It’s really not that hard and it’s edifying to do on your own infrastruc­ture, sidesteppi­ng the usual template-driven webhosts. But once your friends see what you’ve done they’ll want you to host their website, and their friends websites, and soon you’ll be the web hosting king. Either that or you’ll have no friends left on account of none of them knew what they wanted and you told them to go bother some other chump.

Or maybe neither, but if you do find yourself hosting multiple websites or applicatio­ns on the same server then it’s a reasonable idea to isolate them from one another in some way. There’s nothing particular­ly advanced about having different websites on the same box: once you have DNS records correctly set up then any old webserver, with some gentle massaging of configurat­ion files, will happily serve the right pages (based on the URL) from a single host.

This is a little more complicate­d with HTTPS, because the server needs to present a certificat­e before it knows which site is being requested. We won’t get into this, but there’s a solution in the form of the server name indication (SNI) extension to the TLS protocol. HTTPS or not, the problem is that having lots of sites in one place is potentiall­y risky – , especially if they belong to different people.

Ideally, none of the sites that you host will be compromise­d, but if one is and is done so severely enough, then potentiall­y everything on the server becomes vulnerable. There are measures that can be taken to mitigate against this, ranging from the draconian (such as refusing to host anything but static html) to the more permissive (using PHP FPM pools to segregate script access, or Firejail to lock things down a bit more).

Yet we’re still riding the “containeri­se all the things wave”, and hosting multiple websites is a great way to introduce containers. For good measure, we’ll also put our containers behind an Nginx reverse proxy. We could, of course, put that in a container too, but let’s not go crazy ( no,let’snot–Ed). We’re going to use Ubuntu Server 17.04 for this tutorial, but the basics will be the same whatever your distro. We’ll need Nginx and Docker. The former is easy: $ sudo apt install nginx

The version of Docker in the Ubuntu repos (the package is called docker-io – the one called docker is a stylish applicatio­n launcher) is pretty old. It more or less works for this tutorial, but it’s probably a better idea to follow the instructio­ns in the box and get the latest and greatest. You’ll find instructio­ns for other distros at https://docs.docker. com/engine/installati­on/#server.

We’ll start with the plain Nginx image from Dockerhub, which just needs to be pointed to a static html directory. Start the docker daemon and grab this with $ sudo systemctl start docker $ sudo docker pull nginx

To host Wordpress (shudder) sites, we’d need to add PHP and MySQL type things to this image, but we won’t do that. That wheel has already been invented so we’ll use a different pre-fabbed LEMP container later in the tutorial to host some PHP. For now, we’ll create a directory for our static site: $ mkdir -p ~/site1/html

Nobody writes HTML by hand anymore, so this next bit may serve as a history lesson for some. Create an index file with the following: $ nano ~/site1/html/index.html and populate it with some good ol’ fashioned markup: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> LXF static site </title> </head> <body> <h1> HTML – it gets the job done </h1> A simple static site. Isn’t it eye-catching? </body> </html>

The HTML5 specifying header character set are optional, but if you’re going to write HTML, it may as well be by the book. Save this with Ctrl-X, Y. It doesn’t really matter that this file (and the rest of the site1/ directory) is ‘outside’ the container that’s going to use it: from a security point of view the important thing is that it’s ‘outside’ the container which isn’t going to use it. We are, however, going to have to tell

Docker to point our container at the site1/ directory. Nginx usually serves pages from /usr/share/nginx/html/ so we need to map this directory inside the container to our site1/

html/ directory on the host. We could do this with a bind mount from the command line (using the -v switch) every time we bring up the container, but it’s tidier to make a new image based off the old one.

Create a simple Dockerfile with nano ~/site1/Dockerfile and add the following to it: FROM nginx COPY html/ /usr/share/nginx/html Now we can create and tag our new image with: $ cd ~/site1 $ docker build -t lxf-site1 . Next, we can fire up a container built from this image and check that everything works: $ sudo docker run --name lxf1 -d -p 8080:80 lxf-site1

It’s good to name your containers (and probably to do so differentl­y from the underlying image) because it makes them easier to keep track of (for example, via the docker ps command). The -d flag tells Docker to detach and we’ve used -p to forward port 80 on the container to port 8080 on the host. Thus, all going to plan, pointing your web browser at

http://localhost:8080 should display the index page we constructe­d earlier. Later on, we’ll set up a reverse proxy on the host so that appropriat­e traffic can be marshalled to this site based on the hostname requested. For now, we’ll set up another website in another container.

Contain yo’selves

As you might imagine, a ready to go LAMP (or LEMP in our case, E for nginx – remember our pronunciat­ion lesson earlier) stack is pretty handy for all manner of projects. As a result there are a number of pre-rolled images. We’ll use the one from www.linuxconfi­g.org, which will give us a Debian 9 base, nginx, MariaDB and PHP 7. Delicious. Grab it with: $ sudo docker pull linuxconfi­g/lemp

This one’s a couple of hundred megabytes so will take a while. As before, we’ll create a directory for our other website and another to store our database. $ mkdir -p ~/site2/html

$ mkdir ~/site2/mysql $ cd ~/site2/html $ nano index.php

We’ll write some lovely PHP to check that this container is working. The container actually includes a file similar to this one, but we’ll make our own (because everyone loves writing PHP): <?php $dbh = mysql_connect('localhost’, ‘admin’, ‘pass'); if (!$dbh) {

die('Could not connect: ' . mysql_error()); } echo ‘Connected successful­ly to MariaDB database’; mysql_close($dbh); ?> <?php phpinfo(); ?> Save and exit as before. The admin account with password

pass is preconfigu­red with the image. This time we’ll use volumes because they’re the least fussy way of having a persistent database. Data in our container will survive the container being stopped and restarted, but ideally we’d like to be able to spin up the image (or another like it) somewhere else and easily move the data to it. We could use a designated directory on the host for our database (for example, ~/site2/

mysql/), but we would run into all kinds of permission­s issues (translatio­n: we tried this and weird stuff happened that we couldn’t fix). We’ll forward port 80 on the container to port 8081 on the host this time. $ cd ~/site2 $ sudo docker run --name lxf2 -d -p 8081:80 -v $PWD/html:/ var/www/html -v mysql:/var/lib/mysql linuxconfi­g/lemp Again, you’ll get a big long hex string that identifies your container, but it’s easier to refer to it by the name we’ve bestow’d upon it, lxf2 . After a few seconds this container should be accessible via your web browser at

http://127.0.0.1:8081. Hopefully, you’ll be greeted with a successful database connection message and some lovely PHP debug info.

Here we’ve bind mounted the ~/site2/html directory inside the container, which means we can modify it from the host and changes should be reflected instantly. Depending on your purposes you may wish to build a new image and copy this directory into it, as we did earlier. We’ve also created a volume called mysql and we can check the details of this newly created volume with: $ sudo docker volume inspect mysql and this tells us that the volumes are stored in /var/lib/ docker/volumes.

You can put anything you like in the html/ directory – your favourite webapp (Wordpress, phpBB, Nextcloud, for example), or write your own PHP site with its own database, the possibilit­ies are endless. Containers are strange things to get your head around at first: a lot seems unintuitiv­e or inaccessib­le. But they’re your friends really, and if it helps you feel more at home, then navigate them as you would a normal system. Just do: $ docker exec -it lxf2 /bin/bash

The exec keyword runs a command inside the container, the -i option stipulates interactiv­e mode (so that the process doesn’t exit immediatel­y) and t allocates a pseudo-TTY. Together the two options make the container behave like a traditiona­l terminal. Containers by design tend to be quite minimal, so you won’t find a systemd running as PID1 in there. Nor will you find lots of the command line tools you may be used to. Of those that are there, many will not function correctly, for example, top , because various environmen­t settings haven’t been defined. But you can still poke around, and hopefully convince yourself that there’s not too much voodoo going on. Exit the container by typing, most unimaginat­ively, exit .

Perverse Roxy

So far we have created two containers each hosting fairly primitive websites which we can access on our host machine’s ports 8080 and 8081. We also installed nginx on the host, so (knowingly or otherwise) we’re also serving a 404 Not Found page on the host. Visit http://localhost if you don’t believe us.

When Nginx first came into being its modus operandi was not as a webserver, but as what’s known as a reverse proxy. The idea of a proxy is reasonably well known: it’s something that acts as an intermedia­ry between two things. In networking terminolog­y, it’s a server that relays requests from one machine to another. This could be because one machine is behind a firewall and needs the proxy to talk to the outside world, or it could be, as in the case of VPNs, to obfuscate the IP address of the original machine.

At any rate, a reverse proxy is more or less the inverse of both of these, acting as an intermedia­ry for a group of associated servers rather than associated clients. This is good news because it’s just what we need in order to make both of our docker-ised web servers accessible without having to resort to port numbers. Besides routing traffic appropriat­ely, a reverse proxy may be used as a load balancer, distributi­ng traffic to servers hosting the same

content, or as a cache for static content, so those servers don’t get unduly hammered.

Rather than serving a 404 page, we’d like our nginx instance on the host to direct traffic to the appropriat­e nginx container. The marshallin­g will be based on the hostname requested by clients connecting to our host. It’s not necessary (but this is how it would work in the real world) to have DNS records pointing to your host’s IP address, be they paid for registrati­ons or a free service such as Duck DNS. Instead, we can use a well-known web developers trick of putting a couple of entries in our /etc/hosts file. This is checked before Linux attempts to look up DNS records externally so, as far as our machine is concerned, we can give it any hostname we want. We’ll use the dummy .local domain to keep things simple. Add these lines to the hosts file with sudo nano /etc/hosts – you can use a vanity name such as

myawesomes­erver.com if you really want: 127.0.0.1 lxfdocker1.local 127.0.0.1 lxfdocker2.local

Save this and now you should find that both those domains now resolve to our host, so that visiting either of them displays the 404 page again. Progress, but not quite what we want. We need to tell Nginx on the host about our two domains. For our static site do sudo nano /etc/nginx/

conf.d/lxf1.conf and fill in the following: server { listen 80; server_name lxfdocker1.local; location / {

proxy_pass http://127.0.0.1:8080;

}

} Save this file and repeat for our other container, changing the server_name to lxfdocker2.local and the proxy_pass to http://127.0.0.1:8081. Now restart nginx with $ sudo systemctl restart nginx

You should find that http://lxfdocker1.local refers us to our static site, and http://lxfdocker2.local visits our LEMP container. Fantastich. For fully featured proxying, you should look at some

proxy_set_header options in the .conf file, in particular X-Real-IP and X-Forwarded-For . These help pass the client’s details through our reverse proxy, which may be required for more advanced web apps. You may also wish to use IP tables or another firewall to disable direct access to our websites via our host’s external IP to ports 8080 and 8081. There’s no real harm in leaving them accessible at this stage. As long as they are accessible via the loopback address things will still work.

Finally do check out some of the amazing things other people are doing with Docker at the Awesome Docker page: https://github.com/veggiemonk/awesome-docker. LXF

 ??  ?? You’ll soon discover that the Docker hub hosts more images than you can shake a pointy stick at. They’re all just a docker pull away.
You’ll soon discover that the Docker hub hosts more images than you can shake a pointy stick at. They’re all just a docker pull away.
 ??  ?? It’s nice to know that our database and PHP are working. Having the database in a volume means it can be used with another container.
It’s nice to know that our database and PHP are working. Having the database in a volume means it can be used with another container.
 ??  ??
 ??  ?? You could spice up this basic webpage by going full Geocities and adding animated gifs, making judicious use of the <blink> and <marquee> tags.
You could spice up this basic webpage by going full Geocities and adding animated gifs, making judicious use of the <blink> and <marquee> tags.
 ??  ?? loves to dabble with Docker. The number of times he’s wiped out his whole system has been vastly decreased since embracing the new technology Jonni Bidwell
loves to dabble with Docker. The number of times he’s wiped out his whole system has been vastly decreased since embracing the new technology Jonni Bidwell
 ??  ?? Like Docker? Like Minecraft? Then you’ll love Dockercraf­t. Just don’t use it on production systems…
Like Docker? Like Minecraft? Then you’ll love Dockercraf­t. Just don’t use it on production systems…

Newspapers in English

Newspapers from Australia