欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  网络运营

docker连接spring boot和mysql容器方法介绍

程序员文章站 2022-04-25 17:29:58
在之前使用docker部署运行了spring boot的小例子,但是没有使用数据库。在这一篇中,介绍docker如何启动mysql容器,以及如何将spring boot容器...

在之前使用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 	 email 	 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());

总结

以上就是本文关于docker连接spring boot和mysql容器方法介绍的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站:浅谈docker安全机制内核安全与容器之间的网络安全详解docker使用linux iptables 和 interfaces管理容器网络windows使用docker打开新窗口error解决办法等,有什么问题可以随时留言,小编会及时回复大家的。这里推荐几本学习docker的相关书籍,供广大docker爱好者学习参考:

第一本docker书 带书签目录 完整pdf扫描版

docker容器与容器云(第2版) 完整pdf扫描版

希望大家喜欢!