Docker: Apache container with sidecar

Why would you use a sidecar?

e.g. to add something to an existing container without rewriting it.

Assuming you’ve run a container with Apache as in this post: Docker: Apache container then you’ll have an environment variable, APP_ID.

You can use this to run a sidecar container that adds a health metric. E.g.

docker run --pid=container:${APP_ID} -p 8081:8081 brendanburns/topz:db0fa58 /server --addr=0.0.0.0:8081

and now you have a sidecar container running. E.g.

curl localhost:8081

91 9.937410610507195 0.02218294 /server --addr=0.0.0.0:8081
1 0 0.0024320167 httpd -DFOREGROUND
7 0 0.005011428 httpd -DFOREGROUND
8 0 0.0008106722 httpd -DFOREGROUND
9 0 0.0009335013 httpd -DFOREGROUND

 

 

Docker: Apache container

Running Apache in Docker from Ubuntu

Install Docker

curl -fsSL https://get.docker.com | sh

 

To allow you to use Docker as a user

sudo usermod -aG docker <username>

 

Run Docker with Apache image:

sudo docker run -dit –name apache -p 8080:80 -v /tmp/webroot:/usr/local/apache2/htdocs/ httpd:2.4

This will overwrite anything you’ve written to local webroot path.

Also, 8080:80 is host:container.

See also docker container run

 

And docker stop <your container name> will not delete that volume. It persists.

https://docs.docker.com/storage/

 

Test from local machine with:

curl localhost:8080

 

Note: you can access your container ID if you know the container name. E.g. assuming the container name is apache then you can use:

APP_ID=docker ps | grep apache | awk '{print $1}'

 

Docker swarm

What is Docker swarm used for?

This SO post is pretty useful (albeit by a Kubernetes guy):

https://stackoverflow.com/questions/27640633/docker-swarm-kubernetes-mesos-core-os-fleet

TLDR

Swarm is an effort by Docker to extend the existing Docker API to make a cluster of machines look like a single Docker API. Fundamentally, our experience at Google and elsewhere indicates that the node API is insufficient for a cluster API. You can see a bunch of discussion on this here: https://github.com/docker/docker/pull/8859 and here: https://github.com/docker/docker/issues/8781

docker: automatically restart a container

Say you need to restart a VM or restart Docker. How do you restart a container?

E.g. you have:

then restarting Docker (e.g. on the Mac you can click the Docker icon in the toolbar and select Docker > Restart) you get:

whilst Docker is restarting and:

after the restart (i.e. no containers).

 

You can use --restart always

docker container run --restart always -d <image id> sleep 1d

to restart after a docker reboot.

 

This https://docs.docker.com/config/containers/start-containers-automatically/

says

See also https://docs.docker.com/config/containers/live-restore/#enable-live-restore

 

More on Restart Policies

There are 4 restart policies: no, on-failure, unless-stopped, always.

no is the default. i.e. don’t restart if a container stops.

The others are:

always

We’ve seen this before. E.g. let’s say we have a script:

Note: exit 1 indicates an error (exit 0 would indicate success).

which we use as follows:

 

We can build and run with:

This will exit.

To restart with always restart policy use:

docker container run --restart always -d testing_restarts

Now, when it crashes, under docker ps you’ll see:

 

on-failure

Here we can restart a container if it exits with a non-zero exit code. We can also specify a number of retries. E.g.

--restart on-failure:3

docker container run --restart on-failure:3 -d testing_restarts

Notes

  • the container will not restart if you do a docker stop <container id>
  • the container (and oddly even any containers that have stopped as a result of completing the on-failure number of retries – although only the first time the daemon was restarted) WILL restart if you restart the docker daemon

 

unless-stopped

Behaves the same as always except if a container is stopped.

Note: if you manually stop a container its restart policy is ignored until the Docker daemon restarts.

https://docs.docker.com/config/containers/start-containers-automatically/#restart-policy-details

 

Ensuring Containers Are Always Running with Docker’s Restart Policy

 

Live Restore

Lets you keep containers alive when the daemon becomes unavailable,.

https://docs.docker.com/config/containers/live-restore/#enable-live-restore

However, doing this on my installation of Docker gave:

because I was running a swarm service.

More: https://docs.docker.com/config/containers/live-restore/#live-restore-and-swarm-mode

I had to restore to Factory Defaults which means signing in to cloud.docker.com again.

 

DockerFile: WordPress

Let’s take a look at Docker‘izing WordPress.

 

The Docker pull command is:

docker pull wordpress

pull: pulls an image or a repository from a registry. It doesn’t run it. It just means you have the image locally.

https://docs.docker.com/engine/reference/commandline/pull/

 

You can actually run the image using:

docker run --name some-wordpress --link some-mysql:mysql -d wordpress

some-wordpress is going to be the name of the container.

--link is a bit old school. It connects one container to another. i.e. MySQL to WordPress. Nowadays we use user-defined networks – e.g. overlays. https://docs.docker.com/network/links/

WordPress Docker Repo: https://hub.docker.com/_/wordpress/

 

However, before you can run it you’ll need MySQL. So:

docker pull mysql:5.7.24

(Aside: why not use mysql or mysql:latest? ‘cos MySQL 8 changed the password authentication method. See below.)

and then run it with:

docker run --name test-mysql -e MYSQL_ROOT_PASSWORD=test -d mysql:5.7.24

--name is the name you’re giving to the container,

MYSQL_ROOT_PASSWORDis an environment variable that you set which is read in the container. Note: with MySQL this is done programmatically via docker-entrypoint.sh – https://github.com/docker-library/mysql/blob/696fc899126ae00771b5d87bdadae836e704ae7d/8.0/docker-entrypoint.sh . For more on ARG, Environment variables: https://stackoverflow.com/questions/53592879/dockerfile-and-environment-variable/53593826#53593826

and -d means detach.

To specify a tagged version just add it after the image using a colon. E.g. mysql:5.7.24.

 

Once you’ve run it you can test it by exec‘ing in with

docker exec -it test-mysql bash

and running:

mysql -u root -p test

or check logs with:

docker logs test-mysql

E.g.

2018-12-03T14:24:57.091306Z 0 [Note] mysqld: ready for connections.
Version: '5.7.24' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server (GPL)

 

Or even mysql in via another MySQL container using:

docker run -it --link test-mysql:mysql --rm mysql sh -c 'exec mysql -h"$MYSQL_PORT_3306_TCP_ADDR" -P"$MYSQL_PORT_3306_TCP_PORT" -uroot -p"$MYSQL_ENV_MYSQL_ROOT_PASSWORD"'

https://hub.docker.com/_/mysql/

 

So, getting back to WordPress let’s run it now with:

docker run --name test-wordpress --link test-mysql:mysql -d wordpress

and check the logs with:

You should then be able to access your WordPress site on http://localhost:8080

 

Errors

Conflict. The container name “/test-wordpress” is already in use by container

You run

docker run --name test-wordpress --link test-mysql:mysql -d wordpress

and get:

docker: Error response from daemon: Conflict. The container name "/test-wordpress" is already in use by container "0ea70abdaf306d896eb71f3ab585961359f27af23a243b81370bf407d3dd846d". You have to remove (or rename) that container to be able to reuse that name.

You’ve already got a container with that name.

Remove it with: docker rm test-wordpress

https://stackoverflow.com/questions/31676155/docker-error-response-from-daemon-conflict-already-in-use-by-container

This might happen if the container exited and you try and relaunch it.

 

Site can’t be reached

You plug http://localhost:8080 into the web browser but get:

Checking the WordPress logs with docker logs test-wordpress I can see:

however this is a secondary problem. Why are we getting this?

‘cos MySQL 8 introduced a different type of authentication – https://github.com/docker-library/wordpress/issues/313

If you are getting this then you need to use: docker pull mysql:5.7.24 or use a different auth method.

 

Back to the problem at hand – we should still be able to see a (non-functioning) WordPress site on that port. i.e. Apache should be running.

Let’s just do a sanity check:

This 0.0.0.0:8080->80/tcp means the docker host port 8080 is mapped to the container port 80.

https://stackoverflow.com/questions/41798284/understanding-docker-port-mappings

so http://localhost:8080 is correct.

 

It seems the problem really was the lack of MySQL. Using 5.7.24 and looking at the WordPress logs showed (for a successful installation):

 

Installing MySQL and WordPress in under a minute:

https://asciinema.org/a/nW3l0A1hi6wzMde4RUQ1QVPsc?speed=3

 

 

 

 

 

Monitoring containers with Prometheus and Grafana

Architecting Monitoring for Containerized Applications

Why not use Nagios?

Can’t use same method as traditional servers. E.g. putting an agent into a container doesn’t really work.

/metrics exposed for container runtime. Docker uses Prometheus format (i.e. simple text with Key Value format)

Prometheus stores data in time series database.

Prometheus configuration

Is in YAML. E.g.

/etc/prometheus/prometheus.yml

Sections:

scrape_configs

- job_name: <name here>

and

scrape_interval: 60s

Prometheus Dashboard

Status > Targets: lists all monitored targets

Graph > Graph > select from insert metric at cursor

 

Collecting Metrics with Prometheus

Exposing Runtime Metrics with Prometheus

Exposing Application Metrics to Prometheus

Exposing Docker Metrics to Prometheus

Building Dashboards with Grafana