Build a web application development environment that uses Java, MySQL, and Redis with Docker CE for Windows

Overview

This is a memo when a Web application that uses MySQL and Redis is developed and executed in Java (Spring Boot is used as a framework) and an environment is built with Docker CE for Windows. MySQL and Redis are containers that use the official image, and Web applications developed with Spring Boot install and execute OpenJDK in the container that uses the official image of CentOS 7.

The source code can be found at rubytomato / docker-demo-redis.

environment

Build an execution environment for MySQL, Redis, and Web applications

Project directory structure

Since the container is managed and executed by docker-compose, docker-compose.yml is placed in the root directory of the project. Information on each container is separated for each subdirectory.

Under project-root, there are roughly four subdirectories. The demo-redis-spring subdirectory is the project directory for your web application running on the app-server instead of the container.

sub directory description
app-server A directory that stores the Dockerfile and related files of the container that runs the web application.
mysql-server mysql-A directory that stores the Dockerfile and related files of the container that runs the server.
redis-server redis-A directory that stores the Dockerfile and related files of the container that runs the server.
demo-redis-spring This is the project directory of the Web application that uses Spring Boot.

** Directory structure **

/project-root
 |
 +--- docker-compose.yml
 +--- README.md
 |
 +--- /demo-redis-spring
 |      |
 |      +--- pom.xml
 |      |
 |      +--- /src
 |      |      |
 |      |      +--- /main
 |      |      +--- /test
 |      |
 |      +--- /target
 |             |
 |             +--- demo.jar
 |
 +--- /app-server
 |      |
 |      +--- Dockerfile
 |      |
 |      +--- start.sh
 |
 +--- /mysql-server
 |      |
 |      +--- Dockerfile
 |      |
 |      +--- /conf
 |      |      |
 |      |      +--- mysqld.cnf
 |      |
 |      +--- /sql
 |             |
 |             +--- 1_schema.sql
 |             +--- 2_init_memo_data.sql
 |
 +--- /redis-server
        |
        +--- Dockerfile
        |
        +--- /conf
               |
               +--- redis.conf

Container for MySQL server

The image uses the official MySQL.

Dockerfile

FROM mysql:8.0.12

COPY ./conf/mysqld.cnf /etc/mysql/conf.d

COPY ./sql/1_schema.sql /docker-entrypoint-initdb.d
COPY ./sql/2_init_memo_data.sql /docker-entrypoint-initdb.d

Configuration

The contents of /conf/mysqld.cnf are as follows. If you copy this file to /etc/mysql/conf.d in the container, it will be read and reflected when MySQL starts.

[mysqld]
character_set_server = utf8mb4
collation_server = utf8mb4_general_ci

log_output = FILE
general_log = 1
log_queries_not_using_indexes = 1
log_slow_admin_statements = 1
log_syslog = 0
log_timestamps = SYSTEM
long_query_time = 3
slow_query_log = 1

general_log_file = general_query_all.log
log_error = error.log
slow_query_log_file = slow_query.log

log_bin_trust_function_creators = 1

[mysql]
show-warnings

prompt = "\u@\h [\d] > "

SQL Script

If you copy the SQL Script to the container's /docker-entrypoint-initdb.d, it will be executed when the database is initialized.

1_schema.sql

CREATE DATABASE sample_db DEFAULT CHARACTER SET = utf8mb4;

CREATE USER 'test_user'@'%' IDENTIFIED BY 'test_user' PASSWORD EXPIRE NEVER;

GRANT ALL ON sample_db.* TO 'test_user'@'%';

USE sample_db;

CREATE TABLE IF NOT EXISTS memo (
   id BIGINT AUTO_INCREMENT,
   title VARCHAR(255) NOT NULL,
   description TEXT NOT NULL,
   done BOOLEAN DEFAULT FALSE NOT NULL,
   updated TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP(3) NOT NULL,
   PRIMARY KEY (id)
)
CHARACTER SET = utf8mb4,
COLLATE utf8mb4_general_ci;

2_init_memo_data.sql

USE sample_db;

START TRANSACTION;

INSERT INTO memo (title, description, done, updated) VALUES ('title A', 'description A', false, '2018-08-01');
INSERT INTO memo (title, description, done, updated) VALUES ('title B', 'description B', false, '2018-08-02');

COMMIT;

Redis server container

The image uses the official Redis.

By the way, when running a Redis server on Windows, build files were available from Microsoft Archive / redis up to Redis 3.0, but 4.0 and above are provided. Since there is no such thing, you will actually use a virtual environment such as Docker.

Dockerfile

FROM redis:4.0.11

COPY ./conf/redis.conf /usr/local/etc/redis/redis.conf

RUN set -x && \
    touch /var/log/redis.log && \
    chown redis:root /var/log/redis.log && \
    chmod 664 /var/log/redis.log

CMD [ "redis-server", "/usr/local/etc/redis/redis.conf" ]

Configuration

/conf/redis.conf is https://raw.githubusercontent.com/antirez/redis/4.0/redis.conf The following parts have been changed based on. Copy this file to /usr/local/etc/redis/redis.conf in the container and give it as an argument when starting redis-server.

** Before change **

bind 127.0.0.1
logfile ""
# maxclients 10000
# requirepass foobared
appendonly no

** Changes **

# bind 127.0.0.1
logfile /var/log/redis.log
maxclients 100
requirepass foobared
appendonly yes

logfile

In this example, the log is changed to output to /var/log/redis.log in the container, but if the logfile setting is set to the default, it will be output to the standard output (stdout). You can check the log output to the standard output with docker-compose logs.

> docker-compose logs -f redis-server

If you want to monitor redis-cli commands

Use the redis-cli monitor if you want to monitor commands executed by other clients.

> docker-compose exec redis-server redis-cli
127.0.0.1:6379> auth foobared
OK
127.0.0.1:6379> monitor
OK

requirepass

If you comment out bind, you will need to authenticate with auth before running the redis command. Set the password specified by auth at this time with requirepass.

Application server container

The Application server runs the web application developed with Spring Boot. The image used is not the official image of OpenJDK but the official image of CentOS7, and I installed OpenJDK 1.8 with yum.

Dockerfile

I am changing the locale and adding a user called app as the execution user of the web application.

FROM centos:7

RUN set -x && \
    yum update -y && \
    yum install -y java-1.8.0-openjdk java-1.8.0-openjdk-devel && \
    yum reinstall -y glibc-common && \
    yum -y clean all

ENV JAVA_HOME /usr/lib/jvm/java-1.8.0-openjdk

# locale settings
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja

RUN set -x && \
    localedef -i ja_JP -c -f UTF-8 ja_JP.UTF-8 && \
    unlink /etc/localtime && \
    ln -s /usr/share/zoneinfo/Japan /etc/localtime

# application user settings
ENV HOME /home/app

RUN set -x && \
    groupadd app && \
    useradd -g app -d /home/app -s /bin/bash app

WORKDIR $HOME
USER app

COPY start.sh .

EXPOSE 9000

start.sh

A shell for easily running web applications. The container's / var / target is the directory where you mounted / project-root / demo-redis-spring / target on Windows. This mount is written in docker-compose.yml.

#!/bin/bash

set -x

java -Xmx512m -Xms512m -XX:MaxMetaspaceSize=256m -verbose:gc -Xloggc:app-gc.log -jar /var/target/demo.jar

Run the web application when the app-server container starts

In this article, the timing of starting the app-server container and the execution of the web application running in that container are separated, but to execute the web application together with the start of the app-server container, the following line at the end of the Dockerfile To add.

CMD [ "./start.sh" ]

You can check the web application logs with the docker-compose logs command.

> docker-compose logs -f --tail=all app-server
Attaching to app-server
app-server      | + java -Xmx512m -Xms512m -XX:MaxMetaspaceSize=256m -verbose:gc -Xloggc:app-gc.log -jar /var/target/demo.jar
app-server      |
app-server      |   .   ____          _            __ _ _
app-server      |  /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
app-server      | ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
app-server      |  \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
app-server      |   '  |____| .__|_| |_|_| |_\__, | / / / /
app-server      |  =========|_|==============|___/=/_/_/_/
app-server      |  :: Spring Boot ::        (v2.0.4.RELEASE)

// ...abridgement...

docker-compose.yml

version: "3.6"
services:

  mysql-server:
    container_name: mysql-server
    build:
      context: ./mysql-server
    volumes:
      - mysql-data:/var/lib/mysql
    environment:
      TZ: Asia/Tokyo
      MYSQL_ROOT_PASSWORD: password
    ports:
      - 3306:3306
    networks:
      - redis-network
    restart: always
    tty: true

  redis-server:
    container_name: redis-server
    build:
      context: ./redis-server
    environment:
      TZ: Asia/Tokyo
    volumes:
      - redis-data:/data
    ports:
      - 6379:6379
    networks:
      - redis-network
    restart: always
    tty: true

  app-server:
    build:
      context: ./app-server
    environment:
      TZ: Asia/Tokyo
      SPRING_PROFILES_ACTIVE: docker
    volumes:
      - ./demo-redis-spring/target:/var/target
    depends_on:
      - mysql-server
      - redis-server
    ports:
      - 9000:9000
    networks:
      - redis-network
    restart: always
    stdin_open: true
    tty: true

networks:
  redis-network:
    driver: bridge

volumes:
  mysql-data:
    driver: local
  redis-data:
    driver: local

About Spring Profile

When running a Spring Boot application from within the app-server container, set an environment variable called SPRING_PROFILES_ACTIVE to specify a profile called docker.

app-server:
  environment:
    SPRING_PROFILES_ACTIVE: docker

Switches the connection destination of MySQL server and Redis server in the container with the specified profile. The following is an excerpt of the relevant part of the Spring Boot configuration file. In the profile called docker, the host name of MySQL server and Redis server is used as the host name of the container.

application.yml


spring:
  profiles:
    active: dev

  datasource:
    url: jdbc:mysql://localhost:3306/sample_db?useSSL=false&allowPublicKeyRetrieval=true
    username: test_user
    password: test_user

  redis:
    host: localhost
    port: 6379
    ssl: false
    database: 0
    password: foobared

server:
  port: 9001

---

spring:
  profiles: docker
  datasource:
    url: jdbc:mysql://mysql-server:3306/sample_db?useSSL=false&allowPublicKeyRetrieval=true
  redis:
    host: redis-server

server:
  port: 9000

About ports

The port of mysql-server and redis-server container is exposed to the outside as shown below so that the container's Mysql server and Redis server can be accessed when the Web application is executed on Windows. ..

mysql-server

ports:
  - 3306:3306

redis-server

ports:
  - 6379:6379

Build and start / stop container

** Build **

> docker-compose build

When not using the cache

> docker-compose build --no-cache

Start-up

Volume is created at the first startup.

> docker-compose up -d
Creating network "docker-demo-redis_redis-network" with driver "bridge"
Creating volume "docker-demo-redis_mysql-data" with local driver
Creating volume "docker-demo-redis_redis-data" with local driver
Creating mysql-server ... done
Creating redis-server ... done
Creating app-server   ... done

From the next time onward, volume creation will be skipped.

> docker-compose up -d
Creating network "docker-demo-redis_redis-network" with driver "bridge"
Creating mysql-server ... done
Creating redis-server ... done
Creating app-server   ... done

Reboot

> docker-compose restart
Restarting app-server   ... done
Restarting redis-server ... done
Restarting mysql-server ... done

Stop

> docker-compose down
Stopping app-server   ... done
Stopping mysql-server ... done
Stopping redis-server ... done
Removing app-server   ... done
Removing mysql-server ... done
Removing redis-server ... done
Removing network docker-demo-redis_redis-network

Mount the target directory

In order to execute the Web application developed by Spring Boot on the app-server container, mount the target directory where the built jar file is output to / var / target of the app-server container.

  app-server:
    volumes:
      - ./demo-redis-spring/target:/var/target

Run web application

To execute the web application, enter the app-server container with the exec command and execute start.sh copied to the container.

> docker-compose exec app-server bash --login
[app@72e38b38c6ca ~]$ ./start.sh
+ java -Xmx512m -Xms512m -XX:MaxMetaspaceSize=256m -verbose:gc -Xloggc:app-gc.log -jar /var/target/demo.jar

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.4.RELEASE)

2018-08-08 22:09:10.248  INFO 46 --- [           main] com.example.demo.Application             : Starting Application v0.0.1-SNAPSHOT on 72e38b38c6ca with PID 46 (/var/target/demo.jar started by app in /home/app)
2018-08-08 22:09:10.253 DEBUG 46 --- [           main] com.example.demo.Application             : Running with Spring Boot v2.0.4.RELEASE, Spring v5.0.8.RELEASE
2018-08-08 22:09:10.256  INFO 46 --- [           main] com.example.demo.Application             : The following profiles are active: docker

// ...Omitted below...

Since port 9000 of the app-server container is exposed to the outside, access http: // localhost: 9000 / from a browser and confirm that the page is displayed.

MySQL, Redis data persistence

Use named volume.

volumes:
  mysql-data:
    driver: local
  redis-data:
    driver: local

If you want to initialize the data, delete it with the docker volume command.

** Check volume **

> docker volume ls
DRIVER              VOLUME NAME
local               docker-demo-redis_mysql-data
local               docker-demo-redis_redis-data

** Delete volume **

> docker volume rm docker-demo-redis_redis-data
docker-demo-redis_redis-data

If you delete it, it will be created automatically at the next startup.

> docker-compose up -d
Creating network "docker-demo-redis_redis-network" with driver "bridge"
Creating volume "docker-demo-redis_redis-data" with local driver
Creating mysql-server ... done
Creating redis-server ... done
Creating app-server   ... done

Connect to MySQL server from mysql cli

If you want to connect to a MySQL server and work, connect with the mysql command from the mysql-server container.

> docker-compose exec mysql-server mysql -u test_user -p --database=sample_db
Enter password:
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.12 MySQL Community Server - GPL

Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

test_user@localhost [sample_db] >

Connect to Redis server from redis-cli

If you want to connect to the Redis server and work, connect with the redis-cli command from the redis-server container.

> docker-compose exec redis-server redis-cli
127.0.0.1:6379> auth foobared
OK
127.0.0.1:6379> keys *
(empty list or set)

Application server scale out

This is a method to start any number of Application servers as specified.

Modify docker-compose.yml

Set the ports on the side that exposes the ports to the outside as shown below. In this example, we want the maximum number of scale-outs to be 2, so we specified a port range of 9000,9001.

  app-server:
    ports:
#      - 9000:9000
      - 9000-9001:9000

Start-up

When up, use --scale app-server = num to specify the number of app-servers to start in num.

> docker-compose up -d --scale app-server=2
Creating network "docker-demo-redis_redis-network" with driver "bridge"
Creating mysql-server ... done
Creating redis-server ... done
WARNING: The "app-server" service specifies a port on the host. If multiple containers for this service are created on a single host, the port will clash.
Creating docker-demo-redis_app-server_1 ... done
Creating docker-demo-redis_app-server_2 ... done

To execute an arbitrary command in the app-server container, use --index = num, and specify in which container to execute with num.

> docker-compose exec --index=1 app-server bash --login

Check the number of connections to MySQL server

The Java application in this article is designed to make two connections from one instance at the same time. From the results of the show process list below, you can see that Id # 8 and # 9 are connected from 172.22.0.4 and Id # 10 and # 11 are connected from 172.22.0.5.

> show processlist;
+----+-----------------+------------------+-----------+---------+------+------------------------+------------------+
| Id | User            | Host             | db        | Command | Time | State                  | Info             |
+----+-----------------+------------------+-----------+---------+------+------------------------+------------------+
|  4 | event_scheduler | localhost        | NULL      | Daemon  |  843 | Waiting on empty queue | NULL             |
|  8 | test_user       | 172.22.0.4:48354 | sample_db | Sleep   |  674 |                        | NULL             |
|  9 | test_user       | 172.22.0.4:48356 | sample_db | Sleep   |  676 |                        | NULL             |
| 10 | test_user       | 172.22.0.5:40842 | sample_db | Sleep   |  263 |                        | NULL             |
| 11 | test_user       | 172.22.0.5:40844 | sample_db | Sleep   |  265 |                        | NULL             |
| 13 | root            | localhost        | NULL      | Query   |    0 | starting               | show processlist |
+----+-----------------+------------------+-----------+---------+------+------------------------+------------------+
6 rows in set (0.00 sec)

Check the number of connections to the Redis server

You can see that client id # 3 is connected from 172.22.0.4 and id # 4 is connected from 172.22.0.5.

127.0.0.1:6379> client list
id=3 addr=172.22.0.4:37174 fd=9 name= age=1621 idle=1621 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=get
id=4 addr=172.22.0.5:44918 fd=10 name= age=1051 idle=1051 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=get
id=5 addr=127.0.0.1:41110 fd=11 name= age=79 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=client

docker-compose scale

docker-compose scale is deprecated. Use the --scale flag with the up command instead.

This command is deprecated. Use the up command with the --scale flag instead. Beware that using up with --scale flag has some subtle differences with the scale command as it incorporates the behaviour of up command.

Increase or decrease the number of containers to execute

First run only one app-sever.

> docker-compose up -d
Creating network "docker-demo-redis_redis-network" with driver "bridge"
Creating mysql-server ... done
Creating redis-server ... done
Creating docker-demo-redis_app-server_1 ... done

Scale out containers to the specified number

> docker-compose up -d --scale app-server=2
redis-server is up-to-date
mysql-server is up-to-date
WARNING: The "app-server" service specifies a port on the host. If multiple containers for this service are created on a single host, the port will clash.
Starting docker-demo-redis_app-server_1 ... done
Creating docker-demo-redis_app-server_2 ... done

Reduce containers to the specified number

> docker-compose up -d --scale app-server=1
redis-server is up-to-date
mysql-server is up-to-date
Stopping and removing docker-demo-redis_app-server_2 ... done
Starting docker-demo-redis_app-server_1              ... done

Recommended Posts

Build a web application development environment that uses Java, MySQL, and Redis with Docker CE for Windows
Creating a java web application development environment with docker for mac part1
Create a java web application development environment with docker for mac part2
Procedure for building a Rails application development environment with Docker [Rails, MySQL, Docker]
Build a development environment for Django + MySQL + nginx with Docker Compose
Build a development environment for Docker, java, vscode
How to quit Docker for Mac and build a Docker development environment with Ubuntu + Vagrant
Build a SPA for Laravel 6.2 / Vue.js / Nginx / Mysql / Redis with Docker
Build a PureScript development environment with Docker
Build a Wordpress development environment with Docker
Build a Windows application test environment with Selenium Grid, Appium, and Windows Application Driver
I tried to build a Firebase application development environment with Docker in 2020
[Copy and paste] Build a Laravel development environment with Docker Compose Part 2
Build a local development environment for Rails tutorials with Docker (Rails 6 + PostgreSQL + Webpack)
[Copy and paste] Build a Laravel development environment with Docker Compose Participation
Build a development environment for Docker + Rails6 + Postgresql
Build a WordPress development environment quickly with Docker
Prepare a scraping environment with Docker and Java
Build a Java development environment with VS Code
Build Java development environment with WSL2 Docker VS Code
[Environment construction] Build a Java development environment with VS Code!
Try to build a Java development environment using Docker
Install Ubuntu 20.04 in virtual box on windows10 and build a development environment using docker
Until you build a Nuxt.js development environment with Docker and touch it with VS Code
[Rails] [Docker] Copy and paste is OK! How to build a Rails development environment with Docker
Build a local development environment for Open Distro for Elasticsearch with multiple nodes using Docker
[For beginners] Until building a Web application development environment using Java on Mac OS
Docker × Java Building a development environment that is too simple
Deploying a Java environment with Windows Subsystem for Linux (WSL)
Easy environment construction of MySQL and Redis with Docker and Alfred
Java web application development environment construction with VS Code (struts2)
Rails application development environment construction with Docker [Docker, Rails, Puma, Nginx, MySQL]
Build a Node-RED environment with Docker to move and understand
Build a local development environment for Rails tutorials with Docker-Introduce Bootstrap and Font Awesome with Webpack-
Build a web application with Javalin
Build Java development environment (for Mac)
Comparison of WEB application development with Rails and Java Servlet + JSP
Look through Java and MySQL PATH with environment variables [Windows version]
Create a MySQL environment with Docker from 0-> 1
Build a Java development environment on Mac
Build a simple Docker + Django development environment
Build debug environment on container --Build local development environment for Rails tutorial with Docker-
I built a rails environment with docker and mysql, but I got stuck
Let's install Docker on Windows 10 and create a verification environment for CentOS 8!
How to build a Ruby on Rails development environment with Docker (Rails 6.x)
How to build a Ruby on Rails development environment with Docker (Rails 5.x)
Template: Build a Ruby / Rails development environment with a Docker container (Ubuntu version)
Template: Build a Ruby / Rails development environment with a Docker container (Mac version)
# 1 [Beginner] Create a web application (website) with Eclipse from knowledge 0. "Let's build an environment for creating web applications"
Build a Doker-based development environment on Windows 10 Home 2020 ver. Part 1 Until WSL2-based Docker build
[Windows] [IntelliJ] [Java] [Tomcat] Create a Tomcat9 environment with IntelliJ
Building an environment for WordPress, MySQL and phpMyAdmin with Docker Compose on EC2
Build a Laravel / Docker environment with VSCode devcontainer
I built a Java EE environment on AWS and tried running a web application
A bat file that uses Java in windows
Build a simple Docker Compose + Django development environment
Build Apache and Tomcat environment with Docker. By the way, Maven & Java cooperation
[Win10] Build a JSF development environment with NetBeans
Build a development environment to create Ruby on Jets + React apps with Docker
A reminder of Docker and development environment construction
[First team development ②] Build an environment with Docker