-----** 原創 **------
docker的使用現在越來越多,但多個容器的話,還要一個個的安裝,比較麻煩。相比於k8s的“厚重”,docker-compose相對要簡單得多。
這里是一篇使用docker-compose,對spring boot應用進行一個集群(2個docker,多個類似,只要在docker-compose.yml再加boot應用的服務即可)發布的過程。
1. 前言
架構: spring boot使用nginx作為反向代理,redis作為緩存,mysql作為數據庫,全部docker化。
環境: 開發使用win 10筆記本, eclipse ide, maven. 這個是大家平時使用的。當然也有用idea的。
發布環境:百度雲的一個ecs, 1核2G. centos 7.x
本篇是第一部分,主要是spring boot應用。 這里是第二部分
2. spring boot的小應用
一般情況下, spring boot應用都會用到redis, mysql。 本例中redis是作為一個api調用的計數器,每調用一次 /redis, 計數器加1。
同時mysql有一個表,存儲docker-compose命令及其描述(部分,為boot應用提供數據是主要功能)
好了,先來個項目結構圖
然后直接上各種代碼:沒有行號,方便復制粘貼, : )
1) pom.xml

<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>ex.dockercompose</groupId> <artifactId>compose-demo</artifactId> <version>1.0</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.1.RELEASE</version> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <fork>true</fork> <mainClass>ex.dockercompose.DemoApplication</mainClass> </configuration> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
2) DemoApplication.java

@SpringBootApplication public class DemoApplication { public static void main(String... args) { SpringApplication.run(DemoApplication.class, args); } }
3) RedisConfig.java

@Configuration public class RedisConfig { @Autowired private RedisConnectionFactory connectionFactory; @Bean public RedisTemplate<String, Integer> redisTemplate() { RedisTemplate<String, Integer> redisTemplate = new RedisTemplate<>(); RedisSerializer<String> stringSerializer = new StringRedisSerializer(); redisTemplate.setKeySerializer(stringSerializer); redisTemplate.setConnectionFactory(connectionFactory); return redisTemplate; } }
4) CommandController.java

@RestController public class CommandController { @Autowired private CommandService commandService; @GetMapping("/commands") @ResponseBody public List<Command> getCommands() { return commandService.getCommands(); } }
5) RedisController.java

@RestController public class RedisController { @Autowired private RedisTemplate<String, Integer> redisTemplate; @GetMapping("/redis") @ResponseBody public String getValue(HttpServletRequest request) { String localAddress = request.getLocalAddr(); Integer counter = redisTemplate.opsForValue().get("counter"); if(counter == null) { counter = 0; } counter++; redisTemplate.opsForValue().set("counter", counter); return localAddress + " => " + counter; } }
6) CommandDao.java

@Mapper public interface CommandDao { @Select("select id, command, description from command order by id") List<Command> getCommands(); }
7) Command.java

public class Command { private int id; private String command; private String description; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return command; } public void setName(String name) { this.command = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } }
8) CommandService.java

@Service public class CommandService { @Autowired private CommandDao commandDao; public List<Command> getCommands() { return commandDao.getCommands(); } }
9) application-compose.yml (mysql是指docker-compose.yml里的mysql服務名, redis也是)

server.port: 10101 spring: datasource: url: jdbc:mysql://mysql:3306/compose?serverTimezone=GMT%2B8 username: boot password: boot123 redis: host: redis port: 6379 password: redis123
10) application-dev.yml (本地開發時用)

server.port: 10101 spring: datasource: url: jdbc:mysql://127.0.0.1:3306/compose?serverTimezone=GMT%2B8 username: root password: redis: host: 127.0.0.1 port: 6379 password: redis123
11) application.yml (開發時用)
spring.profiles.active: dev
12) build.bat 這個文件稍加說明一下:使用這個腳本,是為了方便。只要鼠標雙擊這個文件即可在同一文件夾里生成 jar文件。
如果不用這個腳本,要在pom.xml所在目錄, cmd里運行 mvn package, 生成的jar會在 target 文件夾里,喜歡用哪個自己選。
del target\compose-demo-1.0.jar call mvn package copy target\compose-demo-1.0.jar . pause
13) compose.sql 初始化數據庫用,這個在第二部分講

-- ---------------------------- -- Create database -- ---------------------------- DROP DATABASE IF EXISTS compose; CREATE DATABASE compose DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci; use compose; SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for command -- ---------------------------- DROP TABLE IF EXISTS `command`; CREATE TABLE `command` ( `id` int(11) NOT NULL AUTO_INCREMENT, `command` varchar(30) DEFAULT NULL, `description` varchar(100) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of command -- ---------------------------- INSERT INTO `command` VALUES ('1', 'build', 'Build or rebuild services'); INSERT INTO `command` VALUES ('2', 'bundle', 'Generate a Docker bundle from the Compose file'); INSERT INTO `command` VALUES ('3', 'config', 'Validate and view the Compose file'); INSERT INTO `command` VALUES ('4', 'create', 'Create services'); INSERT INTO `command` VALUES ('5', 'down', 'Stop and remove containers, networks, images, and volumns'); INSERT INTO `command` VALUES ('6', 'events', 'Receivve real time events from containers'); INSERT INTO `command` VALUES ('7', 'exec', 'Excecute a command in a running container'); INSERT INTO `command` VALUES ('8', 'help', 'Get help on a command');
14) docker-compose.yml 第二部分講

version: '3' services: nginx: image: nginx:1.15 volumes: - ./:/etc/nginx/conf.d ports: - 80:80 - 443:443 links: - spring-boot-1 - spring-boot-2 depends_on: - spring-boot-1 - spring-boot-2 mysql: image: mysql:5.7 volumes: - db_data:/var/lib/mysql restart: always environment: MYSQL_ROOT_HOST: '%' MYSQL_ROOT_PASSWORD: root123 MYSQL_DATABASE: compose MYSQL_USER: boot MYSQL_PASSWORD: boot123 redis: image: redis container_name: my_redis command: redis-server --requirepass redis123 ports: - "6379:6379" spring-boot-1: image: compose-demo:1.0 # build: . # ports: # - "10101:10101" expose: - "10101" restart: always depends_on: - mysql - redis spring-boot-2: image: compose-demo:1.0 # build: . expose: - "10101" restart: always depends_on: - mysql - redis volumes: db_data:
15) Dockerfile 使用application-compose.yml 這個配置文件,在這里設定。

FROM java:8 COPY compose-demo-1.0.jar compose-demo-1.0.jar ENV JAVA_OPTS="" ENTRYPOINT exec java $JAVA_OPTS -Dspring.profiles.active=compose -jar compose-demo-1.0.jar
16) nginx.conf

upstream boots { server spring-boot-1:10101; server spring-boot-2:10101; } server { listen 80; charset utf-8; access_log off; location / { proxy_pass http://boots; proxy_set_header Host $host:$server_port; proxy_set_header X-Forwarded-Host $server_name; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
3. 測試
先用compose.sql 生成相應的數據庫。 然后本地運行一下。 (圖片也不讓縮小了,這是怎么回事,原來可以的。為什么把這個功能去掉了,吐一下。。)
4. 打包
最終要生成 jar 上傳到服務器,所以進入項目文件夾,雙擊build.bat,生成compose-demo-1.0.jar。
好了,本篇基本上是boot應用相關,以及后面會用到的文件內容。 docker相關的部分在第二部分中講解。