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:
- Update the script to expose that port by adding
EXPOSE 8082
right beforeCMD ...
part. Then rebuild with the same command above. - Map that port into host machine when running it.
docker run --rm -p 8989:8082 sancho21/h2:1.4.196
- 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 toVOLUME ["/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 toVOLUME ...?
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, usedocker 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, usedocker 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/