docker连接spring boot和mysql容器
在之前使用docker部署运行了Spring Boot的小例子,但是没有使用数据库。在这一篇中,介绍docker如何启动mysql容器,以及如何将Spring Boot容器与mysql容器连接起来运行。
docker基本命令:
首先熟悉一下在操作过程中常用的docker基本命令:
docker images:列出所有docker镜像
docker ps:列出所有运行中的容器,-a参数可以列出所有容器,包括停止的
docker stop container_id:停止容器
docker start container_name:启动已被停止的容器
docker rm container_id:删除已经停止的容器,加-f选项可以强制删除正在运行的容器
docker rmi image_id:删除镜像,前提是该镜像没有对应的容器
docker运行mysql容器
首先是新建Dockerfile:
FROM ubuntu:14.04
MAINTAINER loveqh
RUN apt-get update
RUN apt-get -y install mysql-server
RUN /etc/init.d/mysql start \
&& mysql -uroot -e "grant all privileges on *.* to 'root'@'%' identified by '123456';" \
&& mysql -uroot -e "grant all privileges on *.* to 'root'@'localhost' identified by '123456';"
RUN sed -Ei 's/^(bind-address|log)/#&/' /etc/mysql/my.cnf \
&& echo 'skip-host-cache\nskip-name-resolve' | awk '{ print } $1 == "[mysqld]" && c == 0 { c = 1; system("cat") }' /etc/mysql/my.cnf > /tmp/my.cnf \
&& mv /tmp/my.cnf /etc/mysql/my.cnf
EXPOSE 3306
CMD ["/usr/bin/mysqld_safe"]
然后创建mysql镜像:
docker build -t loveqh/mysql .
下一步便是由该镜像启动一个容器:
docker run -d -P --name docker-mysql loveqh/mysql
其中,
-d表示在后台运行容器,并会返回容器id
-P是将容器所有暴露的端口映射到主机的随机端口号上,也可以使用-p是指定一容器端口的映射关系,如-p 33060:3306,就是把容器的3306端口映射到宿主机的33060端口上
可以通过docker ps查看容器端口映射关系,在PORTS那一列显示
0.0.0.0:32770->3306/tcp
也就是mysql映射到了宿主机的32770端口上了,那么就可以通过
mysql -h 0.0.0.0 -P 32770 -uroot -p
连接到mysql容器了。
docker连接spring boot和mysql容器
之前的文章中已经在docker中运行了Spring Boot的实例,但是没有用到数据库。接下来我们在项目基础上添加数据库操作。
首先在resources下新建application.properties文件来配置数据库:
spring.datasource.url = jdbc:mysql://localhost:3306/spring spring.datasource.username = root spring.datasource.password = 123456 spring.datasource.driverClassName = com.mysql.cj.jdbc.Driver
注:这里的url会在稍后连接mysql容器后进行修改。
新建 schema.sql文件,Spring Boot在启动时会自动执行该文件,因此可以在该文件里创建数据表和插入测试数据等操作:
use spring;
create table if NOT EXISTS user (
id int PRIMARY KEY NOT NULL auto_increment,
name VARCHAR(30),
password VARCHAR(10),
email VARCHAR(30)
);
-- INSERT INTO user(name, password, email) values("test", "001", "test@163.com");
INSERT INTO user(name, password, email)
SELECT * FROM (SELECT "test", "001", "test@163.com") AS tmp
WHERE NOT EXISTS (
SELECT name FROM user WHERE name='test' AND email='test@163.com'
) limit 1;
在该文件里,指定了所使用的数据库spring,然后如果没有user表则新建。接下来插入测试数据时,注释了简单的插入命令,因为这样会在每次启动项目时都会插入一条相同的记录,因此用下面的语句代替。
按照之前的步骤创建Spring Boot镜像:
docker build -t loveqh/spring-boot-mysql-docker .
下面是连接运行Spring Boot容器并连接到mysql数据库:
docker run -d -p 8088:8080 –name spring-web –link docker-mysql:mysql loveqh/spring-boot-mysql-docker
其中,
-d仍然是在后台运行,如何不想后台运行,可以将-d参数替换为-it,这样可以看到项目的输出信息。当然,也可以通过docker logs container-name/container-id查看容器日志。
-p参数将容器中Spring Boot默认的8080端口映射到了宿主机的8088端口
–name指定了容器的名字,这样在容器停止后可以通过docker start spring-web重启
–link参数连接到了docker-mysql容器,并使用了别名mysql
刚开始一直纠结spring boot项目如何配置mysql地址,因为在运行mysql容器时没有指定端口映射,是随机映射的,并且如果我们在mysql的url中写localhost:映射端口的话,那么我们使用link连接这两个容器的作用也就没有了。终于在看了一些资料后突然醒悟了,使用–link之后,docker会在子容器(这里的spring boot容器)的/etc/hosts中将父容器(这里的mysql容器)与父容器的ip地址绑定,那么我们就可以mysql:3306来访问数据库了。也就是把application.properties中数据库url改为:
spring.datasource.url = jdbc:mysql://mysql:3306/spring
第二个mysql是我们之前设置的别名。
接下来访问http://localhost:8088就可以看到运行结果了。
项目代码
因为本文主要是讲docker连接两个容器的,因此没有对代码进行说明,下面只是简单地粘贴出关键代码。
Index - 首页name:password:email:
//UserController.java
package com.xxx;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.util.List;
/**
* Created by wangl on 17-5-16.
*/
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserDao userDao;
@RequestMapping(method = RequestMethod.GET)
public String index(Model model) {
model.addAttribute("user", new User());
return "index";
}
@RequestMapping("/list")
public String list(Model model) {
Listusers = userDao.findAll();
model.addAttribute("users", users);
return "list";
}
@RequestMapping(value = "/registry", method = RequestMethod.POST)
public String registry(@ModelAttribute(value = "user") User user, Model model) {
boolean flag = userDao.save(user);
if(flag) {
Listusers = userDao.findAll();
model.addAttribute("users", users);
return "list";
}
model.addAttribute("info", "注册失败!");
return "fail";
}
}
//UserDao.java
package com.xxx;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* Created by wangl on 17-5-16.
*/
@Repository
public class UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
public ListfindAll() {
String sql = "select id, name, email from user";
RowMappermapper = (rs, rowNum) -> {
User user = new User();
user.setId(rs.getLong(1));
user.setName(rs.getString(2));
user.setEmail(rs.getString(3));
return user;
};
return jdbcTemplate.query(sql, mapper);
}
public boolean save(User user) {
boolean exists = exists(user);
if(exists) {
return false;
}
String sql = "insert into user(name, password, email) values(?, ?, ?)";
int count = jdbcTemplate.update(sql, user.getName(), user.getPassword(), user.getEmail());
return count == 1;
}
public boolean exists(User user) {
String sql = "select count(*) from user where name=?";
int count = jdbcTemplate.queryForObject(sql, new Object[]{user.getName()},int.class);
return count != 0;
}
}
list - 用户列表
| id | name | stat:index | stat:count | stat:size | stat:current | stat:even | stat:odd | stat:first | stat:last | |
|---|---|---|---|---|---|---|---|---|---|---|
| id,error | name,error | email,error | error | error | error | error | error | error | error | error |
问题记录
在做的过程中遇到了很多问题,经过查资料解决了,现在将其记录下来。
在使用thymeleaf模板引擎时遇到报错:org.xml.sax.SAXParseException: The element type “THYMELEAF_ROOT” must be terminated by the matching end-tag
之前遇到很多thymeleaf报错,都是html标签的闭合问题,仔细检查html文件中标签是否都闭合以及是否对应
在访问index的注册页面时,遇到报错:java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name ‘user’ available as request attribute
这里使用了thymeleaf自动绑定表单进行提交,花了好长时间去检查registry方法和index.html,结果怎么改都出错。后来才发现,原来index页面中有th:object=”${user}”,但是刚开始index方法并没有在model中添加该对象,因此会出现不能获得user的错误。解决办法就是在所有返回index的方法中,都对model添加user对象:
model.addAttribute("user", new User());
关注公众号
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
Redis Cluster 集群扩容与收缩
Redis Cluster 集群伸缩 1. 伸缩原理 Redis提供了灵活的节点扩容和收缩方案。在不影响集群对外服务的情况下,可以为集群添加节点进行扩容也可以对下线节点进行缩容。 我们在Redis Cluster 介绍与搭建这篇文章中搭建了一个三主三从的redis集群(如下图所示)。在搭建 Redis Cluster 通信流程剖析这篇博客中根据源码详细剖析了搭建集群的流程。 本篇博客要讲的是,Redis集群的扩容和缩容过程。 我们先根据Redis Cluster 介绍与搭建将如图的集群搭建起来,查看搭建的效果。 127.0.0.1:6379>clusternodes 29978c0169ecc0a9054de7f4142155c1ab70258b127.0.0.1:6379myself,master-007connected0-5461 8f285670923d4f1c599ecc93367c95a30fb8bf34127.0.0.1:6380master-014967170827853connected5462-10922 66478bda726ae6ba4e8fb55034d...
-
下一篇
JDK动态代理详解
本文主要介绍JDK动态代理的基本原理,让大家更深刻的理解JDK Proxy,知其然知其所以然。明白JDK动态代理真正的原理及其生成的过程,我们以后写JDK Proxy可以不用去查demo,就可以徒手写个完美的Proxy。下面首先来个简单的Demo,后续的分析过程都依赖这个Demo去介绍,例子采用JDK1.8运行。 JDK Proxy HelloWorld packagecom.yao.proxy; /** *Createdbyrobin */ publicinterfaceHelloworld{ voidsayHello(); } packagecom.yao.proxy; importcom.yao.HelloWorld; /** *Createdbyrobin */ publicclassHelloworldImplimplementsHelloWorld{ publicvoidsayHello(){ System.out.print("helloworld"); } } packagecom.yao.proxy; importjava.lang.reflect.Invocatio...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Linux系统CentOS6、CentOS7手动修改IP地址
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- SpringBoot2全家桶,快速入门学习开发网站教程
- MySQL8.0.19开启GTID主从同步CentOS8
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Docker容器配置,解决镜像无法拉取问题
- CentOS8编译安装MySQL8.0.19
- CentOS7设置SWAP分区,小内存服务器的救世主
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- SpringBoot2整合Thymeleaf,官方推荐html解决方案

微信收款码
支付宝收款码