Blog

Posts about technology and arts.

Order of containers in Docker Compose

In Docker Compose you are able to control the startup order of the containers via the depends_on statement. This is documented in Controlling startup order in Compose.

If you have a simple setup, with Tomcat and Postgres, sometimes Postgres will start first, but Compose will initialize Tomcat before Postgres has fully booted. When that happens, you may receive 401, 404, or other application errors.

You can fix it by combining depends_on with a healthcheck. For example:

# File: docker-compose.yml
version: '2.1'
services:
  db:
    container_name: twpg
    build:
      context: .
      dockerfile: Dockerfile.postgres
    restart: always
    ports:
      - "5432:5432"
    healthcheck:
      test: "pg_isready -h localhost -p 5432 -q -U postgres"
      interval: 10s
      timeout: 5s
      retries: 5

  web:
    container_name: twtc
    build:
      context: .
      dockerfile: Dockerfile.tomcat
    restart: always
    depends_on:
      db:
        condition: service_healthy
    links:
      - db
    ports:
      - "80:8080"

In the example docker-compose.yml, there are two containers, db and web. web is running a Tomcat, and db is running Postgres. Web depends on db (see depends_on), and uses a condition service_healthy. Which indicates it depends that that container is healthy.

The healthcheck entry under the db container settings define how to check whether Postgres is running or not. In this case, we are using pg_isready, which is available in the vanilla Postgres 9 container.

It will try 5 times, with a 10 seconds interval, and will time out after 5 seconds. You may have to tune these parameters for your application.

This code snippet is from a pull request submitted to Foxoncz/docker-thingworx.

♥ Open Source

Using AWS MFA without a mobile phone

If you use AWS, the chances are that you use MFA - Multi-factor Authentication - to authenticate. I don’t like to install apps in my mobile phone, unless I need to, so having bought a new phone recently, I decided to find a replacement for Google Authenticator.

There are several command line utilities, browser extensions, libraries, and tools (free and paid) that implement the TOTP - time-based one-time password -, the standard required by Amazon for MFA authentication.

I decided to use a Go tool for the first time: gauth. Note that you won’t be able to use it from home, in case you don’t bring your laptop home. You can have one MFA device linked to your AWS account, so you may have to remove an existing one. Follow these instructions with care :^)

Install Go

sudo apt update && sudo apt upgrade -y
cd tmp/ && wget https://storage.googleapis.com/golang/go1.8.linux-amd64.tar.gz
tar -zxvf go1.*.tar.gz
sudo mv go /usr/local
vim ~/.bashrc

Add the following at the bottom of the file.

GOROOT=/usr/local/go
GOPATH="$HOME/go"
PATH="$GOPATH/bin:$GOROOT/bin:$PATH"

And you can test it with . ~/.bashrc && go version.

Install gauth

Given your environment is correctly set up, you should be able to use the following command to install gauth, and have it available in your $PATH.

go get github.com/pcarrier/gauth

Edit ~/.config/gauth.csv adding a value for the AWS MFA key.

Getting the AWS MFA key

To get the value that you must place in your gauth.csv file, you must add a new MFA device. When asked to scan a QR code, look for an option to enter the manual value. That will give you a long string. That’s the value you are looking for.

Extra: Auto copy-paste from command line

If you would like to quickly copy and paste, try creating an alias as described on this gist.

I used these instructions, and can now run one command line, that will put the next MFA code in my clipboard. Then just paste into my browser, and that’s that!

Happy hacking!

References

Proposed logos for OpenNLP

A couple of logos submitted to OPENNLP-6. Made with Inkscape, fonts from Google Fonts.

Drawing Cave

Apache Commons Lang: Memoizer

The current release of Apache Commons Lang is 3.5. The upcoming release, probably 3.6, will include a new feature, added in a pull request: a Memoizer implementation. Check out the ticket LANG-740 for more about the implementation being added to [lang].

The book Java Concurrency in Practice introduces readers to the Memoizer, and has also a public domain implementation available for download (besides that, the book has also lots of other interesting topics!).

In summary, Memoizer is a simple cache, that will store the result of a computation. It receives a Computable object, responsible for doing something that will be stored by the Memoizer. Here’s a simple code to illustrate how that will work in your Java code.

// Computation to be stored in the cache
Computable<String, String> getFormattedCurrentDate = new Computable<String, String>() {
    @Override
    public String compute(String fmt) throws InterruptedException {
        return new SimpleDateFormat(fmt).format(new Date());
    }
};

// Our memoizer
Memoizer<String, String> dateCache = new Memoizer<>(getFormattedCurrentDate);

// To illustrate its use
for (int i = 0; i < 10; i++) {
    try {
        // S -> Millisecond
        System.out.println(dateCache.compute("HH:mm:ss:S Z dd/MM/YYYY"));
        // Regardless of this sleep call, we get the same result every iteration
        Thread.sleep(1500);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

The computable created (getFormattedCurrentDate) will be called only once, and stored in a map. The parameter passed in the #compute() method will be used as key in the map. So choose your parameter wisely :-) The output of the example will be similar to the following one.

19:15:57:854 +1300 08/01/2017
19:15:57:854 +1300 08/01/2017
19:15:57:854 +1300 08/01/2017
19:15:57:854 +1300 08/01/2017
19:15:57:854 +1300 08/01/2017
19:15:57:854 +1300 08/01/2017
19:15:57:854 +1300 08/01/2017
19:15:57:854 +1300 08/01/2017
19:15:57:854 +1300 08/01/2017
19:15:57:854 +1300 08/01/2017

In the example above I used a for-loop to illustrate what will happen. Even though we call the memoizer #compute() method several times, followed by Thread#sleep(); only one result, the first to be computed, will be returned.

So that’s all for today. Hope you learned something about this new class, that must be available in the next release of Apache Commons Lang.

Happy hacking!

ps: [lang] uses Java 7, so that is why we do not have a functional instead of the Comparable

Subscribe