五、Docker搭建项目实战
2020-03-13 本文已影响0人
Suny____
1、数据持久化
实战前还有一个知识点需要补充,就是持久化。
项目是部署在容器里的,产生的数据也是在容器里的,那如果容器挂了,数据该怎么存,是如何保证持久化的呢?
-
Volume
Docker中数据的持久化就是通过 volume 来实现,将容器中存储数据的目录映射到宿主机中,这样即使容器挂了,数据还是在宿主机中存在的。
我们看 mysql 的Dockerfile,里面就使用了 volume 来映射目录。
FROM debian:buster-slim
# add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added
RUN groupadd -r mysql && useradd -r -g mysql mysql
# ...省略...
# 这个命令会将 /var/lib/mysql 目录映射到宿主机
VOLUME /var/lib/mysql
COPY docker-entrypoint.sh /usr/local/bin/
RUN ln -s usr/local/bin/docker-entrypoint.sh /entrypoint.sh # backwards compat
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 3306 33060
CMD ["mysqld"]
映射文件目录查看:
# 启动mysql容器
[root@10 ~]# docker run -d --name mysql01 -p 3301:3306 -e MYSQL_ROOT_PASSWORD=root --privileged mysql
6e491f8d4177fe71ff2e6a243f63fa2fffc7ee7249e56a7d61d042104e2b1df7
# 进入mysql容器,查看映射的数据目录
[root@10 ~]# docker exec -it mysql01 bash
root@6e491f8d4177:/# cd /var/lib/mysql/
# 这里就是mysql的数据文件
root@6e491f8d4177:/var/lib/mysql# ls -n
total 178200
drwxr-x---. 2 999 999 187 Mar 13 13:05 '#innodb_temp'
-rw-r-----. 1 999 999 56 Mar 13 13:05 auto.cnf
-rw-r-----. 1 999 999 3101251 Mar 13 13:05 binlog.000001
-rw-r-----. 1 999 999 155 Mar 13 13:05 binlog.000002
-rw-r-----. 1 999 999 32 Mar 13 13:05 binlog.index
-rw-------. 1 999 999 1680 Mar 13 13:05 ca-key.pem
-rw-r--r--. 1 999 999 1112 Mar 13 13:05 ca.pem
-rw-r--r--. 1 999 999 1112 Mar 13 13:05 client-cert.pem
-rw-------. 1 999 999 1676 Mar 13 13:05 client-key.pem
-rw-r-----. 1 999 999 5402 Mar 13 13:05 ib_buffer_pool
-rw-r-----. 1 999 999 50331648 Mar 13 13:05 ib_logfile0
-rw-r-----. 1 999 999 50331648 Mar 13 13:05 ib_logfile1
-rw-r-----. 1 999 999 12582912 Mar 13 13:05 ibdata1
-rw-r-----. 1 999 999 12582912 Mar 13 13:05 ibtmp1
drwxr-x---. 2 999 999 143 Mar 13 13:05 mysql
-rw-r-----. 1 999 999 30408704 Mar 13 13:05 mysql.ibd
drwxr-x---. 2 999 999 8192 Mar 13 13:05 performance_schema
-rw-------. 1 999 999 1676 Mar 13 13:05 private_key.pem
-rw-r--r--. 1 999 999 452 Mar 13 13:05 public_key.pem
-rw-r--r--. 1 999 999 1112 Mar 13 13:05 server-cert.pem
-rw-------. 1 999 999 1680 Mar 13 13:05 server-key.pem
drwxr-x---. 2 999 999 28 Mar 13 13:05 sys
-rw-r-----. 1 999 999 12582912 Mar 13 13:05 undo_001
-rw-r-----. 1 999 999 10485760 Mar 13 13:05 undo_002
# 在宿主机中查看映射文件
[root@10 ~]# docker volume ls
DRIVER VOLUME NAME
local af5e05da43fad820680e5e734c97ddda5021973457e4c5dbcc51dc2ca8906ee8
# 通过查看映射文件的详情,可以看到映射目录在什么位置
[root@10 ~]# docker volume inspect af5e05da43fad820680e5e734c97ddda5021973457e4c5dbcc51dc2ca8906ee8
[
{
"CreatedAt": "2020-03-13T13:05:27Z",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/af5e05da43fad820680e5e734c97ddda5021973457e4c5dbcc51dc2ca8906ee8/_data",
"Name": "af5e05da43fad820680e5e734c97ddda5021973457e4c5dbcc51dc2ca8906ee8",
"Options": null,
"Scope": "local"
}
]
# 进入宿主机中的目录
[root@10 ~]# cd /var/lib/docker/volumes/af5e05da43fad820680e5e734c97ddda5021973457e4c5dbcc51dc2ca8906ee8/_data
# 可以看到这里的文件与容器中是一致的
[root@10 _data]# ls -n
total 178200
-rw-r-----. 1 999 999 56 Mar 13 13:05 auto.cnf
-rw-r-----. 1 999 999 3101251 Mar 13 13:05 binlog.000001
-rw-r-----. 1 999 999 155 Mar 13 13:05 binlog.000002
-rw-r-----. 1 999 999 32 Mar 13 13:05 binlog.index
-rw-------. 1 999 999 1680 Mar 13 13:05 ca-key.pem
-rw-r--r--. 1 999 999 1112 Mar 13 13:05 ca.pem
-rw-r--r--. 1 999 999 1112 Mar 13 13:05 client-cert.pem
-rw-------. 1 999 999 1676 Mar 13 13:05 client-key.pem
-rw-r-----. 1 999 999 5402 Mar 13 13:05 ib_buffer_pool
-rw-r-----. 1 999 999 12582912 Mar 13 13:05 ibdata1
-rw-r-----. 1 999 999 50331648 Mar 13 13:05 ib_logfile0
-rw-r-----. 1 999 999 50331648 Mar 13 13:05 ib_logfile1
-rw-r-----. 1 999 999 12582912 Mar 13 13:05 ibtmp1
drwxr-x---. 2 999 999 187 Mar 13 13:05 #innodb_temp
drwxr-x---. 2 999 999 143 Mar 13 13:05 mysql
-rw-r-----. 1 999 999 30408704 Mar 13 13:05 mysql.ibd
drwxr-x---. 2 999 999 8192 Mar 13 13:05 performance_schema
-rw-------. 1 999 999 1676 Mar 13 13:05 private_key.pem
-rw-r--r--. 1 999 999 452 Mar 13 13:05 public_key.pem
-rw-r--r--. 1 999 999 1112 Mar 13 13:05 server-cert.pem
-rw-------. 1 999 999 1680 Mar 13 13:05 server-key.pem
drwxr-x---. 2 999 999 28 Mar 13 13:05 sys
-rw-r-----. 1 999 999 12582912 Mar 13 13:05 undo_001
-rw-r-----. 1 999 999 10485760 Mar 13 13:05 undo_002
上面已经演示了mysql容器映射目录到宿主机,如果容器挂了,可以在将该目录映射给容器,这样就达到了容器持久化数据的目的了。
也来演示一下,在mysql容器中创建一个数据库,之后删除容器:
[root@10 _data]# docker exec -it mysql01 bash
root@6e491f8d4177:/# mysql -uroot -proot
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.19 MySQL Community Server - GPL
Copyright (c) 2000, 2020, 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.
mysql> create database db_test;
Query OK, 1 row affected (0.01 sec)
# db_test 数据库已经创建成功
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| db_test |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
删除mysql容器,重新将文件映射回容器,需要使用参数 -v
指定映射目录
[root@10 _data]# docker rm -f mysql01
mysql01
# 将之前的mysql数据目录映射到mysql容器
[root@10 _data]# docker run -d --name mysql01 -p 3301:3306 -v af5e05da43fad820680e5e734c97ddda5021973457e4c5dbcc51dc2ca8906ee8:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root --privileged mysql
9f6f9eec1e448f5c3b665dc925bed8d236cb1ab976d3884be7643eeb3982ae39
[root@10 _data]# docker exec -it mysql01 bash
root@9f6f9eec1e44:/# mysql -uroot -proot
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.19 MySQL Community Server - GPL
Copyright (c) 2000, 2020, 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.
# 可以看到 db_test 数据库还在
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| db_test |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
大家可能也发现了,映射文件的名称太长,而且如果容器多了,我们根本不知道那个映射文件是对应哪个容器的。
所以也有解决办法,就是在启动容器的时候,就指定一个容易辨识的映射文件名称。
# 指定 mysql01 容器使用 mysql01-volume 映射
[root@10 _data]# docker run -d --name mysql01 -p 3301:3306 -v mysql01-volume:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root --privileged mysql
025caf2cf7c9cb129c14451c539d59dab311c747c01dff53c88fe1048348b419
# 创建出来的volume名称就很容易识别了
[root@10 _data]# docker volume ls
DRIVER VOLUME NAME
local mysql01-volume
[root@10 _data]# docker volume inspect mysql01-volume
[
{
"CreatedAt": "2020-03-13T13:22:31Z",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/mysql01-volume/_data",
"Name": "mysql01-volume",
"Options": null,
"Scope": "local"
}
]
2、Nginx + Spring Boot项目 + MySQL 实战
2.1 容器规划
搭建的容器为 1 个Nginx 容器,3个 Spring Boot 容器,1个 Mysql 容器。
- 网络模式
- 使用自建 brige 网络模式,使用指定的 ip 段,以实现通过容器名称连接目标机器。
- docker network create --subnet=172.18.0.0/24 pro-net
- IP分配
- Nginx Container
- 172.18.0.10
- Mysql Container
- 172.18.0.6
- Spring Boot Container
- 172.18.0.11~172.18.0.13
- Nginx Container
- 映射文件
- Mysql
- mysql-volume
- Mysql

2.2 开始搭建容器
- 创建 network、volume
# 自建 brige 网络模式
[root@10 _data]# docker network create --subnet=172.18.0.0/24 pro-net
4a210633167015f7f37df5744b81a58e5acfe3255bd865113c09ef8f180202d8
# 创建 Mysql 数据映射文件
[root@10 _data]# docker volume create mysql-volume
mysql-volume
- 创建Mysql容器
# 创建Mysql容器,指定 volume、network、ip
[root@10 _data]# docker run -d --name mysql01 -v mysql-volume:/var/lib/mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root --net=pro-net --ip 172.18.0.6 mysql
06a4ced69b7d45dc58ce548c6fdcdb7cc46a5c0bca7958d4df1da7098be1e648
SQL
-- 建表语句
create schema db_test collate utf8mb4_0900_ai_ci;
use db_test;
create table t_user (
id int not null primary key,
username varchar(50) not null
);
-- 基础数据
INSERT INTO db_test.t_user (id, username) VALUES (1, 'sunny');
- 准备Spring Boot项目
- 数据库连接地址直接写
容器名称
- 数据库连接地址直接写

- Controller

-
本地测试
注意本地测试时 项目配置文件中的数据库地址要改成 docker 宿主机的 ip 和 端口

-
将项目打成 jar 包
-
上传 jar 包到Linux中
-
编写 Dockerfile 文件
FROM openjdk:8-jre-alpine MAINTAINER sunny LABEL name="springboot-mybatis" version="1.0" author="sunny" COPY springboot-mybatis-0.0.1-SNAPSHOT.jar springboot-mybatis.jar CMD ["java","-jar","springboot-mybatis.jar"]
-
构建 image 镜像
[root@10 test]# docker build -t springboot-mybatis . Sending build context to Docker daemon 21.59MB Step 1/5 : FROM openjdk:8-jre-alpine 8-jre-alpine: Pulling from library/openjdk e7c96db7181b: Pull complete f910a506b6cb: Pull complete b6abafe80f63: Pull complete Digest: sha256:f362b165b870ef129cbe730f29065ff37399c0aa8bcab3e44b51c302938c9193 Status: Downloaded newer image for openjdk:8-jre-alpine ---> f7a292bbb70c Step 2/5 : MAINTAINER sunny ---> Running in 1ed297ae107d Removing intermediate container 1ed297ae107d ---> e2fd8988f05a Step 3/5 : LABEL name="springboot-mybatis" version="1.0" author="sunny" ---> Running in 707fbebabd33 Removing intermediate container 707fbebabd33 ---> 383323324c94 Step 4/5 : COPY springboot-mybatis-0.0.1-SNAPSHOT.jar springboot-mybatis.jar ---> 95be99409a9e Step 5/5 : CMD ["java","-jar","springboot-mybatis.jar"] ---> Running in 4e0645b2946b Removing intermediate container 4e0645b2946b ---> 8cd79100689b Successfully built 8cd79100689b Successfully tagged springboot-mybatis:latest
-
创建 3 个容器
# 指定 network、ip docker run -d --name springboot-mybatis-01 -p 8081:8080 --net=pro-net --ip 172.18.0.11 springboot-mybatis # 指定 network、ip docker run -d --name springboot-mybatis-02 -p 8082:8080 --net=pro-net --ip 172.18.0.12 springboot-mybatis # 指定 network、ip docker run -d --name springboot-mybatis-03 -p 8083:8080 --net=pro-net --ip 172.18.0.13 springboot-mybatis
-
准备 Nginx 容器
-
准备配置文件
- 创建目录
/tmp/nginx
,创建 nginx.conf 文件
user nginx; worker_processes 1; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; location / { # 使用负载均衡 proxy_pass http://balance; } } # 配置负载均衡的项目地址 upstream balance{ server 172.18.0.11:8080; server 172.18.0.12:8080; server 172.18.0.13:8080; } include /etc/nginx/conf.d/*.conf; }
- 创建目录
-
启动Nginx
# 本地没有镜像会自动拉取, 映射宿主机的 /tmp/nginx/nginx.conf 到容器中的 /etc/nginx/nginx.conf,指定 network、ip docker run -d --name nginx01 -p 80:80 -v /tmp/nginx/nginx.conf:/etc/nginx/nginx.conf --network=pro-net --ip 172.18.0.10 nginx
-
-
通过 Nginx 访问 Spring Boot项目
