Friday, March 2, 2018

How Docker can make your coding life easier

How Docker can make your coding life easier

Have you ever had a situation where you have to use different versions of the same database? Probably because some legacy apps can only work with an old version of the database, while other apps work with a more recent one. If you have, and you had headache, then Docker probably is the answer for you.

So…, what is it?

I won’t tell you more about the architecture in details. TL;DR; Docker is like VM (Virtualbox or VMWare) in a way that both allow you to install many applications a long with their configuration, but different in a way that, Docker is much lighter because all instances of it share the same Linux kernel. It is a way to encapsulate an application and its configuration within a small image. You can install Docker on many popular OSes, including Ubuntu Linux and Windows.

Running an image

“Running an image” also means “creating a container” as container is a running instance of an image.

docker run --rm <account>/<image name>:<tag> command on the 
container

For e.g.

docker run --rm openjdk:8-jre java -version

is only required if your image is not published in Docker official? Option --rm is to automatically remove the container when it exits.

Running a Java app locally using a JRE Docker image

Supposed that you want to run this JAR app using Java 8 image. In a normal environment, you’d run it with:

java -jar h2-1.4.196.jar

To use JRE inside Docker image, you have to map local directory containing the JAR file into a directory inside the Docker image. The directory will be created automatically if it doesn’t exist.

docker run --rm -v c:\Downloads:/app openjdk:8-jre java -jar /app/h2-1.4.196.jar

Creating an image

You can use either Dockerfile or Packer. Packer is more generic, not just for building Docker images. But, IMHO, the parameters used in Packer for Docker build script are also specific. It’s much worth to use Dockerfile instead :)

So, I’m going to tell you how to create image using Dockerfile which is a Docker script file containing instructions how to build an image. Here, we’re going to create a Java image based on openjdk 8, and have a H2 database app installed inside.

FROM openjdk:8-jre

ADD http://central.maven.org/maven2/com/h2database/h2/1.4.196/h2-1.4.196.jar /app.jar

# The final blocking command to run the app
CMD ["java", "-jar", "/app.jar"]

To build it, run:

cd /path/to/dir/containing/docker/script/
docker build -t sancho21/h2:1.4.196 .

To run the image, run:

docker run --rm sancho21/h2:1.4.196

Note about -t:

  • sancho21 => your Docker online account
  • h2 => Name of this image
  • 1.4.196 => Tag

Notice that, port 8082 is not accessible by host machine (your notebook), hence you have to map that docker port into a host port. To do it, do:

  1. Update the script to expose that port by adding EXPOSE 8082 right before CMD ... part. Then rebuild with the same command above.
  2. Map that port into host machine when running it.
    docker run --rm -p 8989:8082 sancho21/h2:1.4.196
    
  3. Open http://localhost:8989 in your browser.

Some useful script commands

# ADD: To add files from local or from URL
ADD http://hello.com/file.sh /opt/install

# RUN: Run anything in the OS of the container
RUN touch /tmp/combination

# Exposing port 3306
EXPOSE 3306

# Defining a variable
ENV OTRS_VER 5.0.15

Storage

Persistency are achievable by either 2 ways

  • Volume is where the exact location in the host system will be determined by Docker. No non-Docker app may have access to it as the location is managed and protected by Docker. It is the most recommended persistency model, as it’s easier to backup.

    This is to specify that this path should persistent directory of the container, even after shutdown: --mount source=myvol,target=/var/lib/mysql which is equivalent to VOLUME ["/var/lib/mysql"]. FYI, source is an optional volume name (recommended to use!).

  • Bind mount is a mapping of your local machine directory into a directory in the container. Non-Docker apps may have access to the directory. This is how to di it: --mount type=bind,source=/home/ichsan/mysql/conf,target=/etc/mysql.conf.d which is equivalent to VOLUME ...?

An example how to start a mysql service using the volume

docker run \
  --mount source=otrs-ssh-volume,target=/etc/mysql/conf.d,readonly \
  --name some-mariadb -e MYSQL_ROOT_PASSWORD=secret mariadb

Read all possible options at Docker website.

Creating a volume

docker volume create --driver vieux/sshfs \
   -o sshcmd=ichs002@10.16.30.11:/tmp/otrs \
   -o password=secret123 otrs-ssh-volume

Read more here

Important options to run an image

  • To let host access an exposed port: -p your_machine_port:internal_docker_port e.g. docker run -p 8081:8080 id.web.michsan/stemmer-spring-boot:1.0
    Then you can access it using localhost:8081

  • To run in background: -d e.g. docker run -d -p 8081:8080 id.web.michsan/stemmer-spring-boot:1.0
    To attach to the daemon, use docker attach TheHashEG12912

    But, when the docker service is restarted (the /etc/init.d/docker),
    it won’t be restarted unless --restart with a certain value is used (TODO).

  • If you want to set your working dir: -w /path/on/internal_docker
    e.g. docker run --rm -v $PWD:/app -w /app sancho21/oracle-java:6 java sancho21.Application

Important commands

  • To list running containers: docker ps (To list stopped ones, use docker ps -f "status=exited")
  • To stop a running container: docker stop TheHashEG12912
  • To start a container: docker start TheHashEG12912
  • To remove a container: docker rm TheHashForEG12912
  • Access its shell (bash): docker exec -i -t TheHashForEG12912 /bin/bash

If you hate using hash, you can use its name.

Docker compose

It is a tool to build an application consisting of multiple containers working together. The configuration file is named docker-compose.yml and you start the app by running docker-compose up. If you use other name like otrs.yml, then you must run it this way docker-compose -f otrs.yml up

The following example will start a wordpress application consisting of a wordpress apache image and a database image.

version: '3.4'

services:

  wordpress:
    image: wordpress
    restart: always
    ports:
    - 8080:80
    environment:
      WORDPRESS_DB_PASSWORD: secret
    links:
    - wordpress_db:mysql

  wordpress_db:
    image: mariadb
    restart: always
    environment:
    MYSQL_ROOT_PASSWORD: secret

A popular alternative to Docker compose is Kubernetes
Ref: https://blog.codeship.com/docker-machine-compose-and-swarm-how-they-work-together/

Saturday, September 7, 2013

Distributed OSGi services in JBoss Fuse

JBoss Fuse (Fuse ESB) is a great container featuring Apache Karaf as OSGi container. It has a great feature called Fabric, on which you can start another container efficiently and do provisioning from any container connected in one Fabric. It means that, you can uninstall bundles from in other container from your current container.

Fabric also allows a bundle to publish services and let them be consumed by other bundles. Not just by bundles in the same container, but in other bundles as long as publishers and consumers are connected in one Fabric.

I'm here not to to tell you how to use JBoss Fuse or what it is. But to tell you that it's been hard to find references about how to publish services and consume them in distributed environment. So, I want to share my experience to handle that with blueprint or with Spring DM 1.x.x based on scattered sources of information I have read for weeks.


Monday, April 1, 2013

SELECT ... FOR UPDATE with Spring JDBC

SELECT ... FOR UPDATE is required to lock specific row in database in order to prevent other query thread to read or make changes to the same row. The lock is released once you update the data or commit it.

As a Spring lover, it's hard to find references about implementing the technique in Spring JDBC template. But finally I managed to use it.

Monday, December 31, 2012

Using other kernels with DSIXDA's kitchen

I love using modified kernels, if they support swap partition, overclocking, etc. They may unleash the beast inside my phone.

But, instead of compiling kernel myself which probably may destabilize your phone/device, I prefer to use a stable kernel from another popular ROM which is compatible with my phone/device. That popular kernel will be the core of my new ROM built with DSIXDA's kitchen.

Saturday, December 29, 2012

How to create Android Custom ROM

Some of you probably wonders: "Why another ROM?", "Why not using existing custom ROM?". So, this is my answer. Some ROMs are created specifically to a specific radio. Therefore, ROMs from Europe may be not compatible with devices from Asia. I don't know, what the cause of it. In my case, using Europe ROMs may cause bootloop into my Asia device. So, I have to create my own ROM.

How to create it? You see, a lot of ROM enhancers (I'm not saying 'creator' since they do not create it but modifying either stock ROMs or another custom ROMs) use DSIXDA's kitchen to make ROMs. I'm going to tell you how to create a little bit super ROM from stock ROM using the kitchen in Ubuntu :D (Sorry, I'm not too good at Windows). This tips works on HTC Wildfire S, but more or less may be working on other devices.

Wednesday, December 26, 2012

Unlocking HTC Wildfire S

I was wondering how people managed to install different kind of Android. I was afraid and said to my self "Is it safe?", "Will it brake my phone?". HTC Wildfire S' small memory gives me no choice but to hack my phone. After searching about "how to root", "how to install custom ROM", etc, I'm finally able to share this experience with you.

Tuesday, December 25, 2012

Creating REST based Webservice with Apache CXF

As you know, there are 3 types of webservice out there named, RPC/Encoded type, Document/Literal/SOA type and REST type. But, the most supported ones are the RPC and Document types.

REST type gives you a lot of flexibility. This is how to create the server and the corresponding client using Apache CXF.