spring-boot-nginx代理-docker-compose部署
在本地测试,使用docker部署不用在意环境
java测试项目:
- web框架:spring boot 框架
- 项目管理:maven
- 数据库:redis + postgres + mongo
- 部署相关:nginx + docker-compose
项目目录:
项目结构如图,废话不多说,上代码
一、本地web代码测试和打包jar
1、首先需要本地代码能跑起来
2、打包成jar,(具体打包查看spring官网:http://spring.io/guides/gs/rest-service/),打包后,在target目录下生成一些文件夹和文件,重要的看项目结构图红框圈中的文件,就是它:gs-spring-boot-0.1.0.jar
(命令打包:mvn clean package -DskipTests )
二、使用jar包制作docker镜像
使用docker把jar文件做成镜像,使用Dockerfile方式
Dockerfile内容:
FROM java:8 ADD ./target/gs-spring-boot-0.1.0.jar app.jar RUN bash -c 'touch /app.jar' ENTRYPOINT ["java","-jar","/app.jar"]
注意:Dockerfile文件放哪随便(不要放到target下),路径不一样,需要更改 ADD指令后面的路径地址,确保能通过相对路径找到并添加jar包
进入到Dockerfile所在目录,执行docker build 命令,制作镜像:
docker build -t java_compose .
点".",代表使用当前路径下的Dockerfile文件,可以不进入Dockerfile所在目录执行build命令,需要把 点“.” 换成绝对路径或相对路径,找到Dockerfile文件
然后可以查看镜像:
docker images
redis、postgres、mongo、nginx镜像都是从官方拉取的镜像,不多少了
三、docker-compose.yml文件
docker-compose.yml:
version: '3' services: nginxxx: image: nginx:latest container_name: nginxxx restart: unless-stopped ports: - 8080:80 volumes: - ./nginx.conf:/etc/nginx/conf.d/default.conf //docker容器启动停止,内部配置消失,所以挂在外面的配置文件,不会丢失 redisxx: image: redis:latest container_name: redisxx restart: unless-stopped env_file: .env ports: - 6378:6379 # volumes: # - redis-data:/bitnami/redis postgresxx: image: postgres:latest container_name: postgresxx restart: unless-stopped env_file: .env command: postgres -c 'max_connections=200' ports: - 5431:5432 environment: - POSTGRES_USER=testdb //创建用户名 - POSTGRES_PASSWORD=testdb //创建密码 有这两个参数,可以不用再创建数据库,会默认创建和用户名一样的数据库,如果想创建其他的数据库名字,可以再加参数POSTGRES_DB=your_db_name # volumes: # - pg-data:/var/lib/postgresql/data mymongoxx: image: mongo:latest container_name: mymongoxx restart: unless-stopped env_file: .env ports: - 27016:27017 environment: - MONGO_INITDB_ROOT_USERNAME=testdb //创建root用户名 - MONGO_INITDB_ROOT_PASSWORD=testdb //创建root用户密码 注意:创建用户名和密码后,会开启auth认证,xxxx_application.properties需要配置认证数据库配置信息spring.data.mongodb.authentication-database=admin - MONGO_INITDB_DATABASE=testdb //创建集合(数据库) # volumes: #- mongo-data:/data/db javaxx: image: java_compose:latest restart: always container_name: javaxx ports: - 9002:9001 depends_on: - postgresxx - redisxx - mymongoxx environment: - REDIS_HOST=redisxx //host注意:只写容器名字,不用加http:// - REDIS_PORT=6379 - POSTGRES_URL=postgresql://postgresxx:5432/testdb?useSSL=false //注意,没有http:// - POSTGRES_USERNAME=testdb - POSTGRES_PASSWORD=testdb - MONGO_URL=mongodb://testdb:testdb@mymongoxx:27017/
四、Nginx配置文件
因为使用docker容器,配置文件需要挂载
nginx.conf
map $http_upgrade $connection_upgrade { default upgrade; '' close; proxy_ignore_client_abort on; } server { listen 80; server_name localhost; location / { proxy_pass http://javaxx:9002; proxy_set_header Host $proxy_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
因为使用docker-compose部署,都是容器间通讯,所以地址都是容器的名字,javaxx就是项目容器名字(docker-compose.yml文件里面的container_name:javaxx)
五、环境变量
其实为了省事,环境变量都写在docker-compose.yml里面了,如果还有其他变量不方便写到yml文件里,可以写到.env文件,docker-compose.yml文件会去.env文件读取变量
六、docker-compose启动
进入到docker-compose目录,执行命令:
docker-compose -f docker-compose.yml up
停止:
docker-compose -f docker-compose.yml down
如果有容器启动失败,可以查看log,看看到底什么原因造成的
docker logs -f 容器名
OK,搞定
=============================分割线================================
主要代码:
application.properties
server.port=9002 # Redis数据库索引(默认为0) spring.redis.database=0 # Redis服务器地址 spring.redis.host=${REDIS_HOST:localhost} # Redis服务器连接端口 spring.redis.port=${REDIS_PORT:6379} #postgresql: #DB properties: spring.datasource.url=jdbc:${POSTGRES_URL:postgresql://localhost:5432/testdb?useSSL=false} spring.datasource.username=${POSTGRES_USERNAME:testdb} spring.datasource.password=${POSTGRES_PASSWORD:testdb} spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL9Dialect spring.jpa.hibernate.ddl-auto=update spring.jpa.generate-ddl=true spring.data.mongodb.uri=${MONGO_URL:mongodb://testdb:testdb@localhost:27017/} spring.data.mongodb.database=testdb # docker-compose 配置了MONGO_INITDB_ROOT_USERNAME和MONGO_INITDB_ROOT_PASSWORD,需要auth认证,这样就需要设置认证的数据库 # 同时配置了MONGO_INITDB_DATABASE=admin, 所以这里设置admin为认证数据库 spring.data.mongodb.authentication-database=admin
pom.xml:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.springframework</groupId> <artifactId>gs-spring-boot</artifactId> <version>0.1.0</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.9.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency> </dependencies> <properties> <java.version>1.8</java.version> </properties> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
Application.java:
package com.main; import java.util.Arrays; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; @SpringBootApplication(scanBasePackages = {"com.main"}) //扫描com.main路径下的文件 public class Application { public static void main(String[] args) { ApplicationContext ctx = SpringApplication.run(Application.class, args); System.out.println("Let's inspect the beans provided by Spring Boot:"); String[] beanNames = ctx.getBeanDefinitionNames(); Arrays.sort(beanNames); for (String beanName : beanNames) { System.out.println(beanName); } } }
--------
postgres相关:
ResponseUser.java:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.main.responseUser; import java.util.HashMap; import java.util.Map; public class ResponseUser extends HashMap<String, Object> { private static final long serialVersionUID = 1L; public ResponseUser() { put("code", 0); } public static ResponseUser error(Integer code,String msg) { return error(code, msg); } public static ResponseUser error(int code, String msg) { ResponseUser r = new ResponseUser(); r.put("code", code); r.put("msg", msg); return r; } public static ResponseUser ok(Object msg) { ResponseUser r = new ResponseUser(); r.put("msg", msg); return r; } public static ResponseUser ok(Map<String, Object> map) { ResponseUser r = new ResponseUser(); r.putAll(map); return r; } public static ResponseUser ok() { return new ResponseUser(); } @Override public ResponseUser put(String key, Object value) { super.put(key, value); return this; } }
User.java:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.main.models; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "sys_user") public class User implements Serializable{ private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id", nullable = false) private Integer id; @Column(nullable = false, name = "name") private String name; @Column(nullable = false, name = "age") private Integer age; public static long getSerialVersionUID() { return serialVersionUID; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
UserRepository.java:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.main.repository; import com.main.models.User; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import java.util.List; public interface UserRepository extends JpaRepository<User, Long> { // 查 User findByName(String name); User findByAge(Integer age); List<User> findByNameAndAge(String name, Integer age); List<User> findByNameLike(String name); @Query("from User u where u.name=:name") User findUser(@Param("name") String name); // 改 @Modifying @Query("update User u set u.age=:age where u.id=:id") void findByUpdateUser(@Param("id") Integer id,@Param("age") Integer age); // 删除的两种方式 User findById(Integer id); void delete(User obj); @Modifying @Query("delete from User u where u.id=:id") void findByIdDeleteUser(@Param("id") Integer id); }
UserService.java:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.main.service; public class UserService { }
UserController.java:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.main.controllers; import com.main.models.User; import com.main.repository.UserRepository; import com.main.responseUser.ResponseUser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.bind.annotation.*; import javax.transaction.Transactional; import java.util.List; @Service @RestController @RequestMapping("/test") public class UserContoller { private final static Logger LOGGER = LoggerFactory.getLogger(UserContoller.class); @Autowired private UserRepository userRepository; // 增 @PostMapping("/user") public User saveUser(@RequestBody User us){ User user = new User(); user.setName(us.getName()); user.setAge(us.getAge()); userRepository.save(user); return user; } // 删 @Transactional @DeleteMapping("/user/{id}") public ResponseUser deleteUser(@PathVariable(name="id") Integer id) { // User u = userRepository.findById(id); // userRepository.delete(u); // return u; userRepository.findByIdDeleteUser(id); return ResponseUser.ok(); } // 查询 @GetMapping("/users") public List<User> searchUser(@RequestParam(name = "name") String name,@RequestParam(name = "age") Integer age){ LOGGER.info("获取"); List<User> u = userRepository.findByNameAndAge(name, age); return u; } // 改 @Transactional @PutMapping("/user") public ResponseUser updateUser(@RequestBody User us){ try{ userRepository.findByUpdateUser(us.getId(), us.getAge()); }catch (Exception e){ e.printStackTrace(); return ResponseUser.error(407, "更新失败"); } return ResponseUser.ok(); } }
mongo相关:
Customer.java:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.main.models; import org.springframework.data.annotation.Id; public class Customer { @Id public String id; public String firstName; public String lastName; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public Customer(String firstName, String lastName){ this.firstName = firstName; this.lastName = lastName; } @Override public String toString(){ return String.format( "Customer[id=%s, firstName='%s', lastName='%s']", id, firstName, lastName ); } }
CustomerService.java:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.main.service; import com.main.models.Customer; public interface CustomerService { boolean insertCustomerIntoMongo(Customer ct); Customer getCustomerFromMongoByFirstName(String firstName); boolean updateCustomerToMongo(String firstName, String lastName); Customer deleteCustomerFromMongo(String firstName); }
Impl/CustomerServiceImpl.java:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.main.service.Impl; import com.main.models.Customer; import com.main.service.CustomerService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; import org.springframework.stereotype.Service; @Service public class CustomerServiceImpl implements CustomerService { protected static Logger logger = LoggerFactory.getLogger(CustomerServiceImpl.class); @Autowired private MongoTemplate mongoTemplate; // 增 public boolean insertCustomerIntoMongo(Customer ct){ try{ mongoTemplate.save(ct); return true; }catch (Exception e){ logger.error("insertCustomerIntoMongo error: {}", e); return false; } } // 查 public Customer getCustomerFromMongoByFirstName(String firstName){ Query query = new Query(Criteria.where("firstName").is(firstName)); Customer customer = mongoTemplate.findOne(query, Customer.class); return customer; } // 改 public boolean updateCustomerToMongo(String firstName, String lastName){ Query query = new Query(Criteria.where("firstName").is(firstName)); Update update = new Update(); update.set("lastName", lastName); try { mongoTemplate.updateFirst(query, update, Customer.class); return true; }catch (Exception e){ return false; } } // 删 public Customer deleteCustomerFromMongo(String firstName){ Customer customer = new Customer("小李", "飞刀1"); Query query = new Query(Criteria.where("firstName").is(firstName)); mongoTemplate.findAndRemove(query, Customer.class); return customer; } }
CustomerController.java:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.main.controllers; import com.main.models.Customer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import com.main.service.CustomerService; import java.util.Map; @RestController @RequestMapping("/test") public class CustomerController { private final static Logger LOGGER = LoggerFactory.getLogger(CustomerController.class); @Autowired private CustomerService customerService; // 增 @PostMapping("customer") public boolean save(@RequestBody(required = true)Map<String, Object> map){ String firstName = map.get("firstName").toString(); String lastName = map.get("lastName").toString(); Customer customer = new Customer(firstName, lastName); boolean status = customerService.insertCustomerIntoMongo(customer); return status; } // 查 @GetMapping("/customer") public Customer get(@RequestParam(name = "firstName") String firstName){ Customer customer = customerService.getCustomerFromMongoByFirstName(firstName); return customer; } // 改 @PutMapping("/customer") public boolean update(@RequestBody(required = true)Map<String, Object> map){ String firstName = map.get("firstName").toString(); String lastName = map.get("lastName").toString(); boolean status = customerService.updateCustomerToMongo(firstName, lastName); return status; } // 删 @DeleteMapping("/customer") public Customer delete(@RequestParam(name = "firstName") String firstName){ Customer customer = customerService.deleteCustomerFromMongo(firstName); return customer; } }
CustomerRepository.java:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.main.repository; import com.main.models.Customer; import org.bson.types.ObjectId; import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.stereotype.Repository; import java.util.List; @Repository public interface CustomerRepository extends MongoRepository<Customer, ObjectId> { // // 查询 // Customer findByFirstName(String firstName); // List<Customer> findByLastName(String lastName); // // // 改 // // // 删 // void delete(Customer obj); }
redis操作相关:
RedisService.java:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.main.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; @Component public class RedisService { @Autowired private StringRedisTemplate redisTemp; public boolean set(String key, String value){ try{ redisTemp.opsForValue().set(key, value); return true; }catch(Exception e){ e.printStackTrace(); return false; } } public String get(String key){ return redisTemp.opsForValue().get(key); } }
RedisController.java:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.main.controllers; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RequestMapping; import com.main.service.RedisService; @RestController @RequestMapping(value = "/test/redis",method = RequestMethod.GET) public class RedisController { @Autowired private RedisService redisService; @RequestMapping("/set") public String set(){ redisService.set("key1", "value1"); return "ok"; } @RequestMapping("/get") public String get(){ String value = redisService.get("key1"); return value; } }