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
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
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;
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
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.
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
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
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
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 **
> 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
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
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.
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
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] >
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)
This is a method to start any number of Application servers as specified.
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
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
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)
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.
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