docker連接spring boot和mysql容器方法介紹
在之前使用docker部署運(yùn)行了Spring Boot的小例子,但是沒(méi)有使用數(shù)據(jù)庫(kù)。在這一篇中,介紹docker如何啟動(dòng)mysql容器,以及如何將Spring Boot容器與mysql容器連接起來(lái)運(yùn)行。
docker基本命令
首先熟悉一下在操作過(guò)程中常用的docker基本命令:
docker images:列出所有docker鏡像 docker ps:列出所有運(yùn)行中的容器,-a參數(shù)可以列出所有容器,包括停止的 docker stop container_id:停止容器 docker start container_name:?jiǎn)?dòng)已被停止的容器 docker rm container_id:刪除已經(jīng)停止的容器,加-f選項(xiàng)可以強(qiáng)制刪除正在運(yùn)行的容器 docker rmi image_id:刪除鏡像,前提是該鏡像沒(méi)有對(duì)應(yīng)的容器 docker運(yùn)行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"]
然后創(chuàng)建mysql鏡像:
docker build -t loveqh/mysql .
下一步便是由該鏡像啟動(dòng)一個(gè)容器:
docker run -d -P --name docker-mysql loveqh/mysql
其中,
-d表示在后臺(tái)運(yùn)行容器,并會(huì)返回容器id
-P是將容器所有暴露的端口映射到主機(jī)的隨機(jī)端口號(hào)上,也可以使用-p是指定一容器端口的映射關(guān)系,如-p 33060:3306,就是把容器的3306端口映射到宿主機(jī)的33060端口上
可以通過(guò)docker ps查看容器端口映射關(guān)系,在PORTS那一列顯示
0.0.0.0:32770->3306/tcp
也就是mysql映射到了宿主機(jī)的32770端口上了,那么就可以通過(guò)
mysql -h 0.0.0.0 -P 32770 -uroot -p
連接到mysql容器了。
docker連接spring boot和mysql容器
之前的文章中已經(jīng)在docker中運(yùn)行了Spring Boot的實(shí)例,但是沒(méi)有用到數(shù)據(jù)庫(kù)。接下來(lái)我們?cè)陧?xiàng)目基礎(chǔ)上添加數(shù)據(jù)庫(kù)操作。
首先在resources下新建application.properties文件來(lái)配置數(shù)據(jù)庫(kù):
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會(huì)在稍后連接mysql容器后進(jìn)行修改。
新建 schema.sql文件,Spring Boot在啟動(dòng)時(shí)會(huì)自動(dòng)執(zhí)行該文件,因此可以在該文件里創(chuàng)建數(shù)據(jù)表和插入測(cè)試數(shù)據(jù)等操作:
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;
在該文件里,指定了所使用的數(shù)據(jù)庫(kù)spring,然后如果沒(méi)有user表則新建。接下來(lái)插入測(cè)試數(shù)據(jù)時(shí),注釋了簡(jiǎn)單的插入命令,因?yàn)檫@樣會(huì)在每次啟動(dòng)項(xiàng)目時(shí)都會(huì)插入一條相同的記錄,因此用下面的語(yǔ)句代替。
按照之前的步驟創(chuàng)建Spring Boot鏡像:
docker build -t loveqh/spring-boot-mysql-docker .
下面是連接運(yùn)行Spring Boot容器并連接到mysql數(shù)據(jù)庫(kù):
docker run -d -p 8088:8080 –name spring-web –link docker-mysql:mysql loveqh/spring-boot-mysql-docker
其中,
-d仍然是在后臺(tái)運(yùn)行,如何不想后臺(tái)運(yùn)行,可以將-d參數(shù)替換為-it,這樣可以看到項(xiàng)目的輸出信息。當(dāng)然,也可以通過(guò)docker logs container-name/container-id查看容器日志。
-p參數(shù)將容器中Spring Boot默認(rèn)的8080端口映射到了宿主機(jī)的8088端口
–name指定了容器的名字,這樣在容器停止后可以通過(guò)docker start spring-web重啟
–link參數(shù)連接到了docker-mysql容器,并使用了別名mysql
剛開(kāi)始一直糾結(jié)spring boot項(xiàng)目如何配置mysql地址,因?yàn)樵谶\(yùn)行mysql容器時(shí)沒(méi)有指定端口映射,是隨機(jī)映射的,并且如果我們?cè)趍ysql的url中寫(xiě)localhost:映射端口的話,那么我們使用link連接這兩個(gè)容器的作用也就沒(méi)有了。終于在看了一些資料后突然醒悟了,使用–link之后,docker會(huì)在子容器(這里的spring boot容器)的/etc/hosts中將父容器(這里的mysql容器)與父容器的ip地址綁定,那么我們就可以mysql:3306來(lái)訪問(wèn)數(shù)據(jù)庫(kù)了。也就是把a(bǔ)pplication.properties中數(shù)據(jù)庫(kù)url改為:
spring.datasource.url = jdbc:mysql://mysql:3306/spring
第二個(gè)mysql是我們之前設(shè)置的別名。
接下來(lái)訪問(wèn)http://localhost:8088就可以看到運(yùn)行結(jié)果了。
項(xiàng)目代碼
因?yàn)楸疚闹饕侵vdocker連接兩個(gè)容器的,因此沒(méi)有對(duì)代碼進(jìn)行說(shuō)明,下面只是簡(jiǎn)單地粘貼出關(guān)鍵代碼。
Index - 首頁(yè)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", "注冊(cè)失??!");
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
問(wèn)題記錄
在做的過(guò)程中遇到了很多問(wèn)題,經(jīng)過(guò)查資料解決了,現(xiàn)在將其記錄下來(lái)。
在使用thymeleaf模板引擎時(shí)遇到報(bào)錯(cuò):org.xml.sax.SAXParseException: The element type “THYMELEAF_ROOT” must be terminated by the matching end-tag
之前遇到很多thymeleaf報(bào)錯(cuò),都是html標(biāo)簽的閉合問(wèn)題,仔細(xì)檢查html文件中標(biāo)簽是否都閉合以及是否對(duì)應(yīng)
在訪問(wèn)index的注冊(cè)頁(yè)面時(shí),遇到報(bào)錯(cuò):java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name ‘user' available as request attribute
這里使用了thymeleaf自動(dòng)綁定表單進(jìn)行提交,花了好長(zhǎng)時(shí)間去檢查registry方法和index.html,結(jié)果怎么改都出錯(cuò)。后來(lái)才發(fā)現(xiàn),原來(lái)index頁(yè)面中有th:object=”${user}”,但是剛開(kāi)始index方法并沒(méi)有在model中添加該對(duì)象,因此會(huì)出現(xiàn)不能獲得user的錯(cuò)誤。解決辦法就是在所有返回index的方法中,都對(duì)model添加user對(duì)象:
model.addAttribute("user", new User());
總結(jié)
以上就是本文關(guān)于docker連接spring boot和mysql容器方法介紹的全部?jī)?nèi)容,希望對(duì)大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站:淺談Docker安全機(jī)制內(nèi)核安全與容器之間的網(wǎng)絡(luò)安全、詳解Docker使用Linux iptables 和 Interfaces管理容器網(wǎng)絡(luò)、Windows使用docker打開(kāi)新窗口error解決辦法等,有什么問(wèn)題可以隨時(shí)留言,小編會(huì)及時(shí)回復(fù)大家的。這里推薦幾本學(xué)習(xí)docker的相關(guān)書(shū)籍,供廣大docker愛(ài)好者學(xué)習(xí)參考:
第一本Docker書(shū) 帶書(shū)簽?zāi)夸?完整pdf掃描版
http://www.dbjr.com.cn/books/514869.html
Docker容器與容器云(第2版) 完整pdf掃描版
http://www.dbjr.com.cn/books/569549.html
希望大家喜歡!
相關(guān)文章
Docker容器自啟動(dòng)的實(shí)現(xiàn)方法
這篇文章主要介紹了Docker容器自啟動(dòng)的實(shí)現(xiàn)方法,詳細(xì)的介紹了Docker的 Restart policy命令,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2018-09-09
Docker端口映射實(shí)現(xiàn)網(wǎng)絡(luò)訪問(wèn)的方法
本篇文章主要介紹了Docker端口映射實(shí)現(xiàn)網(wǎng)絡(luò)訪問(wèn)的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-07-07
idea?連接遠(yuǎn)程?docker?并部署項(xiàng)目到?docker的過(guò)程
這篇文章主要介紹了idea連接遠(yuǎn)程docker并部署項(xiàng)目到docker,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-10-10
Docker Compose多容器部署的實(shí)現(xiàn)
這篇文章主要介紹了Docker Compose多容器部署的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10
Docker 倉(cāng)庫(kù)管理和Docker Dockerfile詳解
倉(cāng)庫(kù)(Repository)是集中存放鏡像的地方,以下介紹一下 Docker Hub,當(dāng)然不止 docker hub,只是遠(yuǎn)程的服務(wù)商不一樣,操作都是一樣的,對(duì)Docker 倉(cāng)庫(kù)管理相關(guān)知識(shí)感興趣的朋友一起看看吧2023-11-11
docker run啟動(dòng)的容器掛掉了數(shù)據(jù)怎么辦
這篇文章主要介紹了docker run啟動(dòng)的容器掛掉了,數(shù)據(jù)怎么辦,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-09-09
基于docker Desktop一鍵式搭建k8s環(huán)境的步驟
在docker desktop中一鍵啟動(dòng)k8s環(huán)境很簡(jiǎn)單,下面介紹如何啟動(dòng)dashboard,dashboard儀表盤(pán)是新手學(xué)習(xí)k8s至關(guān)重要的一個(gè)工具,本文給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧2023-11-11

