Docker Container with Java and MySql

We need now a container that should be able to execute a spring boot application (jar) and a linked mysql db.

For this we need a docker compose file and a Dockerfile

Dockerfile for Java

FROM openjdk:11
COPY ./app ./app
CMD java -Djava.net.preferIPv4Stack=true -jar /app/JavApp.war

In this example we use the java version 11 (openjdk)

Then we copy all file (actually only the jar file) from our local folder (./app) to the container folder (/app)

Finally we execute the command line to execute the jar file, adding also some java parameter

Docker compose for java and mysql

version: "3.8"
services:
  mysqldb:
    image: mysql
    environment:
      MYSQL_ROOT_PASSWORD: thisIsTheRootPwd
      MYSQL_DATABASE: fconsulting
      MYSQL_USER: fconsuser
      MYSQL_PASSWORD: fconspassword
    ports:
      - "3306:3306"
    volumes:
      - ./dbdata:/var/lib/mysql
  app:
    depends_on:
      - mysqldb
    build: 
      context: .
      dockerfile: Dockerfile
    ports:
      - 8081:8080
    environment:
      JDBC_CONNECTION_STRING: 'jdbc:mysql://mysqldb:3306/fconsulting?allowPublicKeyRetrieval=true&useSSL=false'
      JDBC_PWD: 'fconspassword'
      JDBC_USER: 'fconsuser'
      ClientId: '...'
      ClientSecret: '...'
      mongourl: 'mongodb+srv://...'
    stdin_open: true
    tty: true

In the same folder of Dockerfile we have our docker compose yaml file. The most intersting part is the environment field in which we specify all the system props needed by our java application

Container with Apache, PHP and MySql

Create a new file named docker-composer.yml

version: "3.8"
services:
  php:
    container_name: php8apache
    image: php:8.1-apache
    volumes:
      - ./html:/var/www/html
    ports:
      - 8080:80
 

version: “3.8” is the docker compose version to use

services: is the section where to specify all the pieces of our composition

php: is the service name, you can name it as you want

container_name is an optional filed in which you specify the name of this service container

image: php:8.1-apache, means that our service will be implemented starting from php image and version 8.1-apache

volumes: – ./html:/var/www/html in this case we are associating our local folder ./html to the container folder /var/www/html

ports: – 8080:80 we are binding the local port 8080 to the container port 80

To execute the container with docker compose let’s type the following code:

docker-compose up -d

After it finishes to download artifacts we can try to reach the address http://localhost:8080

Try to personalize the index.php page in the folder ./html adding a index.php file

Add MySql service

At the bottom of our docker yaml file we should add a new mysql service:

version: "3.8"
services:
  php:
    container_name: php8apache
    image: php:8.1-apache
    volumes:
      - ./html:/var/www/html
    ports:
      - 8080:80
    depends_on: 
      - mysql
  mysql:
    image: mysql
    environment:
      MYSQL_ROOT_PASSWORD: thisIsTheRootPwd
      MYSQL_DATABASE: fconsulting
      MYSQL_USER: fconsuser
      MYSQL_PASSWORD: fconspassword
    ports:
      - "9906:3306"

We added the mysql section defining environment parameters and ports to map

The image used is mysql (:latest)

Moreover we added also the depend_on parameter in the php section, because our php service depends on the mysql service to work.

But that is not enough, because, like we would do in a normal environment, we need to install in our container also the php library to make php work with mysql.

To do so we need a Dockerfile in which we specify the php-apache version + the libraries we need.

So create a Dockerfile in the same folder of docker-compose.yaml (actually you can create this docker file wherever you want) and put this code:

FROM php:8.1-apache
RUN docker-php-ext-install mysqli && docker-php-ext-enable mysqli
RUN apt-get update && apt-get upgrade -y

FROM php:8.1-apache is the image that we already specified in the docker-compose file

RUN … are the linux commands to download libraries and download updates

Because we are using a Dockerfile to download the image we should update the docker compose file removing, from php section, the “imagine” section replacing it with the docker section:

version: "3.8"
services:
  php:
    container_name: php8apache
    build: 
      context: .
      dockerfile: Dockerfile
    volumes:
      - ./html:/var/www/html
    ports:
      - 8080:80
    depends_on: 
      - mysql
  mysql:
    image: mysql
    environment:
      MYSQL_ROOT_PASSWORD: thisIsTheRootPwd
      MYSQL_DATABASE: fconsulting
      MYSQL_USER: fconsuser
      MYSQL_PASSWORD: fconspassword
    ports:
      - "9906:3306"

in the build section we specify from which dockerfile to read the imagine and eventually all the other instruction to build our layer.

Now it’s ok.

Add PhpMyAdmin

What is MySql without PhpMyAdmin? Nothing! 😛

So let’s add PhP My Admin to the docker compose:

version: "3.8"
services:
  php:
    container_name: php8apache
    build: 
      context: .
      dockerfile: Dockerfile
    volumes:
      - ./html:/var/www/html
    ports:
      - 8080:80
    depends_on: 
      - mysql
  mysql:
    image: mysql
    environment:
      MYSQL_ROOT_PASSWORD: thisIsTheRootPwd
      MYSQL_DATABASE: fconsulting
      MYSQL_USER: fconsuser
      MYSQL_PASSWORD: fconspassword
    ports:
      - "9906:3306"
  phpmyadmin:
    image: phpmyadmin
    ports:
        - '8090:80'
    environment:
        PMA_HOST: mysql
    depends_on:
        - mysql

imagine: phpmyadmin (:latest) is the original phpmyadmin imagine from docker hub

ports: – ‘8090:80’, I chose 8090 but feel free to use whatever port you want

environment: PMA_HOST, mysql it is the reference to which db to use with phpmyadmin

depends_on: – mysql, this service depends on mysql server

To access with phpmyadmin use root as user and the MYSQL_ROOT_PASSWORD as password.

That’s it

Container

A Container ia basically an Image that is executed.

To execute a container you can use the following command:

docker container run [OPTIONS] <imagename> [COMMAND] [ARG]

where

[OPTIONS], is the flags used to execute the command

[COMMAND] is the instruction that you could execute the container if we don’t like the default command inside the image

[ARG] is the param that we can pass to the container

What does it happen when we launch a container?

First of all Docker tries to find the image locally. If it doesn’t find it it serach into Docker hub.

If we don’t specify a tag the “latest” will be used.

And finally we have our container!

Docker will assign a virtual IP in the private network of the container. After that the binding will be executed

Example

To see all important aspects let’s instantiate a nginx container sing 1.19.5-alpine image

P.S.: Alpine is a Linux distribuition

docker container run -it --rm -d -p 8080:80 --name web nginx:1.19.5-alpine

where:

-it, is a combination of -i and -t, where -i means interact with the standard input and -t interact with the container with a tty interface

-rm, the container will be automatically deleted once terminated

-d, once instantiated the execution will be in background mode

-p 8080:80, the container port 80 will be linked to the 8080 port of the host

–name web, give the “web’ name to the container

once executed you can reach the server at the address http://localhost:8080

Add a volume

In order to associate a local volume (folder) to a container folder we need to add a param in our command line which map our local folder to container folde:

-v /your/local/folder:/container/folder

So the new complete command line will be:

docker container run -it --rm -d -p 8080:80 --name web -v /your/local/folder:/container/folder nginx:1.19.5-alpine

In our specific example, we would point the container folder /usr/share/nginx/html, in which there is the html folder for nginx to our local, previously created, folder /Users/xxx/nginx/html, to override that specifi folder

docker container run -it --rm -d -p 8080:80 --name web -v /Users/xxx/nginx/html:/usr/share/nginx/html nginx:1.19.5-alpine
Dockerizing

if we want to create images we need a file: Dockerfile.

It is a sort of assembler of different pieces. Each of this piece is a layer

It also specifies how the container will be built

SINTAX

FROM

Each Dockerfile must start with FROM.

It specifies the imagine from which to start. For instance:

FROM alpine:latest

ARG

In some case it is possible to add an variable to pass as an argument to the FROM command

for instance:

ARG IMG_VERSION=latest
FROM alpine:${IMG_VERSION}

RUN

RUN command allows to execute one o more instructions, defined in bash command, in a new layer.

Adding in this way an immutable block to the image

CMD

CMD is the default instruction to execute the Container.

Basically it means that at the run of the container this instruction will be executed.

It is executed every time the container starts.

it is like the RUN command but the difference is that the RUN command is executed during the build, the CMD command is not included into the build, but it is executed every time the container is started.

Let’s try to create an image

create a folder in which we will create our artifacts

mkdir dockerfolder

inside this folder create the file Dockerfile

nano Dockerfile

and inside the file past this content:

ARG VERSION=3.8

FROM alpine:$VERSION

LABEL maintainer="gf@fconsulting.tech"

ARG VERSION

# RUN command in bash mode
RUN echo $VERSION

# RUN COMMAND in exec mode
RUN ["echo", "$VERSION" ]

CMD [ "/bin/sh"]

Now let’s remain in the same Dockerfile folder and execute the following command:

docker image build .

if everything went well, if you execute a docker image ls you should find the new image.

To create the image with a name and tag we should add -t to the build command, something like this:

docker image build . -t ourfirstimage:0.1
Docker CLI

Image list installed on your machine

docker image ls

Download docker image

docker image pull <docker image name>

Remove a docker image

docker image rm <docker image name or hash code>

Execute a container:

docker container run <docker image name>

Show running containers:

docker container ls

Show all container, also the one that are not running in that moment:

docker container ls --all

Remove a container

docker container rm <container name>

Start and stop container:

docker container start <container name>
docker container stop <container name>
Docker Images

Docker Images (DI) are like Classes for java, and defines a Docker Container.

DI is not one element but It is a set of (reusable) layers. Each layers is a service/program/OS/file.

For instance, when we pull an image we get a result like this:

giuseppefanuzzi@Giuseppes-MacBook-Pro ~ % docker pull mysql      
Using default tag: latest
latest: Pulling from library/mysql
46ef68baacb7: Pull complete
94c1114b2e9c: Pull complete
ff05e3f38802: Pull complete
41cc3fcd9912: Pull complete
07bbc8bdf52a: Pull complete
6d88f83726a9: Pull complete
cf5c7d5d33f7: Pull complete
9db3175a2a66: Pull complete
feaedeb27fa9: Pull complete
cf91e7784414: Pull complete
b1770db1c329: Pull complete
Digest: sha256:15f069202c46cf861ce429423ae3f8dfa6423306fbf399eaef36094ce30dd75c
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest

DI are built in Layers. layers will receive an ID (SHA256)

Images ids are represented with SHA256 values derived based on his SHA256 layers.

DI are immutables, once built the files can’t be modified.

The hash value of an image is referred as “tag’ name.

When we pull an image normally we specify his name and sometimes his tag

For instance:

The REPOSITORY column represents the name.

The image tag name is the couple NAME:TAG.

For instance “hello-world:latest”

Docker Hello world

After having installed docker on your operating system (with Windows you need a Linux VM) we can try to say our first hello world typing

docker run hello-world

This will end up with a lot of interesting things to learn.

First of all on how to run a container: docker run <containername>

Then, in the output of this command we can see that, if the container is not found locally, docker client runtime will try to download the image it from his repository (docker hub). Then it will create the container starting from the downloaded image.

the second time you execute the same command it will find the container locally avoiding to download it again.

Installing Docker

Installing Docker on different platforms is a straightforward process. Here are step-by-step instructions for installing Docker on macOS, Linux, and Windows:

Installing Docker on macOS:

Prerequisites:

  • macOS 10.13 (High Sierra) or later.
  • An Intel-based Mac. Docker does not support Apple Silicon (M1) natively at the time of my last knowledge update in September 2021, so for M1 users, you may need additional workarounds like using Rosetta or an emulator.

Installation Steps:

  1. Visit the Docker Desktop for Mac download page: Docker Desktop for Mac
  2. Click the “Download for Mac” button to download the Docker Desktop for Mac installer.
  3. Open the downloaded DMG file and drag the Docker application to your Applications folder.
  4. Launch Docker by searching for “Docker” in your Applications folder or using Spotlight.
  5. Once Docker is running, you should see a Docker icon in your menu bar. Click on it to access Docker settings and manage containers.
  6. Docker is now installed and ready to use on your macOS.

Installing Docker on Linux:

Note: The steps for installing Docker on Linux can vary depending on your distribution. Here, we’ll cover the installation process for Ubuntu, a popular Linux distribution.

Installation Steps (for Ubuntu):

  1. Open a terminal window.
  2. Update the package list on your system:
    sudo apt-get update
  3. Install the necessary packages to allow apt to use a repository over HTTPS and ensure compatibility:
    sudo apt-get install apt-transport-https ca-certificates curl software-properties-common
  4. Download and add the Docker GPG key to your system:
    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
  5. Add the Docker repository to your APT sources:
    echo "deb [signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
  6. Update the package list again:
    sudo apt-get update
  7. Finally, install Docker:
    sudo apt-get install docker-ce docker-ce-cli containerd.io
  8. Start and enable Docker to run on system boot:
    sudo systemctl start docker sudo systemctl enable docker
  9. You can verify the installation by running:
    sudo docker --version

Installing Docker on Windows:

Prerequisites:

  • Windows 10 64-bit: Pro, Enterprise, or Education editions.
  • Hyper-V and Containers Windows features enabled.

Installation Steps:

  1. Visit the Docker Desktop for Windows download page: Docker Desktop for Windows
  2. Click the “Download for Windows” button to download the Docker Desktop for Windows installer.
  3. Run the downloaded installer. If prompted, allow the installer to make changes to your device.
  4. Follow the installation wizard, which includes enabling Hyper-V and Containers features if they are not already enabled.
  5. Once the installation is complete, Docker Desktop for Windows will launch automatically. You should see the Docker icon in your system tray.
  6. Docker is now installed and ready to use on your Windows machine.

Depending on your Linux distribution or specific Windows version, there may be slight variations, so it’s always a good idea to consult the official Docker documentation for the most up-to-date and detailed instructions.

What is Docker

Welcome to the world of Docker, where containerization transforms the way we develop, ship, and manage applications.

In this beginner-friendly post, we’ll embark on a journey to understand the fundamental concepts of Docker, setting up Docker on different platforms, and exploring its real-world applications. By the end of this session, you’ll have a solid grasp of what Docker is and how it can revolutionize your software development process.

Understanding Containerization

Containerization is like magic for software developers. It allows you to package an application and its dependencies into a single unit, known as a container. Think of it as a self-contained box that holds everything your app needs to run smoothly, from libraries to system tools. Containers are lightweight, efficient, and highly portable.

A container is

  • an isolated runtime inside of Linux
  • provides a private space under Linux
  • run under any modern Linux kernel

his container has

  • his own process space
  • his own network interface
  • his own disk space

Run as root (inside the container)

Docker vs. Traditional Virtualization

Before Docker, virtualization was the go-to method for running multiple applications on a single server. However, it had its drawbacks. Virtual machines (VMs) are resource-intensive and slower to start. Docker containers, on the other hand, are much more lightweight, as they share the host OS kernel, making them faster and more efficient.

Use Cases for Docker

Docker is incredibly versatile and finds applications across various industries. It’s used for software development, testing, and production deployments. Whether you’re a developer, system administrator, or data scientist, Docker can streamline your workflow and simplify application management.

Setting up Docker

Installing Docker on Various Platforms

Getting started with Docker is easy, regardless of your operating system. Docker provides installation packages for Windows, macOS, and Linux. It’s a matter of a few clicks or commands to have Docker up and running on your machine.

To install Docker on your machin check this post

Exploring Docker Desktop (for Windows and macOS)

For Windows and macOS users, Docker Desktop is a user-friendly tool that simplifies container management. It provides a graphical interface to manage containers, images, and more. It’s a great starting point for those new to Docker.

Docker Versioning and Compatibility

Docker evolves rapidly, with frequent updates and new features. It’s important to understand Docker’s versioning and compatibility matrix to ensure that your containers work seamlessly across different environments.

Docker terminology

Docker Image, representation of a docker container. For instance like a JAR or WAR.

Docker Container, the runtime of Docker. Basically a deployed and running docker image, the instance of the docker image.

Docker Engine, the code which manages Docker stuff. Creates and runs Docker containers

Docker Editions

Docker Enterprise and Community editions

Docker Enterprise, is a Caas (Container as a Service) platform subscription (payed)

Docker Community is a free Docker edition


Question 1: What is containerization?

a) A process of shipping physical containers with software inside
b) A way to package applications and their dependencies
c) A type of virtual machine
d) A tool for managing servers

Correct answer: b) A way to package applications and their dependencies

Question 2: What is a key advantage of Docker containers over traditional virtual machines?

a) Docker containers are more secure
b) Docker containers are larger in size
c) Docker containers share the host OS kernel
d) Docker containers have a GUI

Correct answer: c) Docker containers share the host OS kernel

Question 3: Which of the following is NOT a common use case for Docker?

a) Simplifying application deployment
b) Creating virtual machines
c) Building and testing applications
d) Scaling applications on-demand

Correct answer: b) Creating virtual machines

Question 4: Which platforms does Docker provide installation packages for?

a) Windows, macOS, Linux
b) Windows only
c) macOS only
d) Linux only

Correct answer: a) Windows, macOS, Linux

Question 5: What is Docker Desktop primarily used for?

a) Creating virtual machines
b) Managing Docker containers and images
c) Writing code
d) Playing games

Correct answer: b) Managing Docker containers and images

Question 6: Why is it essential to be aware of Docker’s versioning and compatibility?

a) To ensure your containers work consistently across environments
b) To track the stock market
c) To play the latest video games
d) To learn about new Docker features

Correct answer: a) To ensure your containers work consistently across environments