I tried to create a simple API with Spring Boot and Docker. There weren't many articles that explained from 0 at all, so I will make it myself and post it. However, honestly, I have little knowledge about API and Docker, so please point out any mistakes! Also, please forgive me because it is assumed that it will be built on Mac this time.
・ OS: Mac ・ DB: MySQL (mariaDB) ・ VM: Docker ・ Language: Spring Boot (Java 8) -Build tool: Maven
https://docs.docker.com/docker-for-mac/install/ Please download and install from this URL.
Download from here http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
This time I am using 1.8.0-181.
Anything in particular regarding the Maven version is fine, but this time I will use 3.5.2
.
Please refer to here.
How to install a specific version of Maven
I will install it with brew home.
$ brew install mysql
STS (Spring Tool Suite) is an Eclipse-like IDE that includes spring. This time we will use this to create a project. https://spring.io/tools/sts/all Let's install from here.
Now that we have everything we need, we can start production.
Create an API to CRUD an Entity with User (name, email).
The API to create is as follows.
GET / api / users => Get all users (getUsers) GET / api / users / {id} => Get User with id (getUser) POST / api / users => Add User (createUser) PUT / api / users / {id} => User update (updateUser) DELETE / api / users / {id} => Delete User with id (deleteUser)
file -> new -> Spring Starter Project
I will make a project with.
This time I will make it with the project name " sampleApi
".
Create a project by selecting jpa, web, lombok, mysql in Spring Initializr.
Create Entity, Repository, Service.
Entity
@Data
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue
private Long id;
private String name;
private String email;
}
To put it simply, Entity is a place to store the values to be registered / updated in the DB and the values obtained from the DB. The database table to be exchanged with @Table is specified. We will create this table etc. later.
Repository
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}
This Repository is the class that directly communicates with BD.
Service
@Service
@Transactional
public class UserService {
@Autowired
UserRepository userRepository;
public User findUser(Long id){
return userRepository.findOne(id);
}
public List<User> findUsers(){
return userRepository.findAll();
}
public User save(User user) {
return userRepository.save(user);
}
public void delete(Long id) {
userRepository.delete(id);
}
}
Business logic processing is performed in this Service class. You receive the value from the controller described below and instruct the Repository to process it.
Controller Create a Controller for exchanging Users. Describe the process corresponding to the HTTP request. If you replace User with the resource name, you can use it for other resources. I did not specify the Response code this time, but if you want to implement it strictly, it may be better to specify it?
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
UserService userService;
@RequestMapping(method = RequestMethod.GET)
public List<User> getUsers() {
return userService.findUsers();
}
@RequestMapping(method=RequestMethod.GET, value="{id}")
public User getUser(@PathVariable("id") Long id) {
return userService.findUser(id);
}
@RequestMapping(method=RequestMethod.POST)
public User createUser(@Validated @RequestBody User user) {
return userService.save(user);
}
@RequestMapping(method=RequestMethod.PUT, value="{id}")
public User updateUser(@PathVariable("id") Long id, @RequestBody User user) {
user.setId(id);
return userService.save(user);
}
@RequestMapping(method=RequestMethod.DELETE, value="{id}")
public void deleteUser(@PathVariable("id") Long id) {
userService.delete(id);
}
}
@ RestController
is an annotation for creating Rest API, and you can exchange with @ Controller
+ @ ResponseBody
+ JSON. It handles what spring-boot-starter-web receives and displays in Jackson.
Docker It's docker. I am still ambiguous, so I will write it briefly. First of all, the files "docker-compose.yml" and "Dockerfile" are required to launch the Docker container, so create these two files directly under the project folder.
After creating it, I will write the contents of the file
** First of all, " docker-compose.yml
"**
version: '3'
services:
db:
image: mariadb:10.2
restart: always
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_USER: hogeuser
MYSQL_PASSWORD: password
MYSQL_DATABASE: sampleapi_development
ports:
- "3306:3306"
volumes:
- ./docker/tmp/mysql:/var/lib/mysql
- ./docker/mysql/initdb.d:/docker-entrypoint-initdb.d
volumes:
data:
driver: local
It is a description to start the database server. It also creates a database when you start the server. That is here
MYSQL_ROOT_PASSWORD: password
MYSQL_USER: hogeuser
MYSQL_PASSWORD: password
MYSQL_DATABASE: sampleapi_development
From the top, it is the password for root privileges, the server user name, password, and database name.
** Then " Dockerfile
"**
FROM openjdk:jdk-alpine
VOLUME /tmp
RUN mkdir /app
WORKDIR /app
ENV JAVA_OPTS=""
ENV JAR_TARGET "sampleApi-1.0.0-SNAPSHOT.jar"
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar build/libs/sampleApi-1.0.0-SNAPSHOT.jar" ]
Regarding docker-compose.yml
, I think that it works by copying, but for Dockerfile
, it is necessary to change "sampleApi-1.0.0-SNAPSHOT.jar" of ʻENV and ʻENTRY POINT
a little. This is a description that targets the jar file generated when the project is built, but the file name generated by the project will be different. Please rewrite it referring to the following.
I think there is "pom.xml" in the project, so it's in it
<artifactId>sampleApi</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
I think there is such a description. As you can see, look at the contents of this "ʻartifactId", "
version"and"
packeging`" and rewrite it.
Next, fill in the contents of "ʻapplication.properties`". The file here is in "src / main / resources". Fill in the following:
spring.datasource.url=jdbc:mysql://localhost:3306/sampleapi_development
spring.datasource.username=hogeuser
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
This is what you need to connect the project and the database, and describes the user name and database name created in "docker-compose.yml" above.
Now that the creation is complete, we will actually start it. First, use the command to move to just below the project.
$ cd ~/sampleApi
Let's start Docker. Type in the following:
$ docker-compose up --build
If there are no errors, it is successful.
Now let's launch the application. I thought, but I haven't created the contents (table) of the database yet, so I will create it. You need to go inside the database server launched by Docker. First, type the following to check the server name.
$ docker-compose ps
Name Command State Ports
------------------------------------------------------------------------------
sampleapi_db_1 docker-entrypoint.sh mysqld Up 0.0.0.0:3306->3306/tcp
Now that you know the server name, let's enter.
$ docker exec -it sampleapi_db_1 bash
root@c71a21817893:/# mysql -h localhost -P 3306 -u hogeuser -p
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 20
Server version: 10.2.16-MariaDB-1:10.2.16+maria~bionic mariadb.org binary distribution
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]>
Check if the database has been created.
MariaDB [(none)]> show databases;
+-----------------------+
| Database |
+-----------------------+
| information_schema |
| sampleapi_development |
+-----------------------+
2 rows in set (0.06 sec)
MariaDB [(none)]>
There is no problem
Let's make a table.
Click here for create statement
CREATE TABLE users ( id int NOT NULL AUTO_INCREMENT, name varchar(255) NOT NULL, email varchar(255) NOT NULL, PRIMARY KEY (id) );
However, I don't think it can be done as it is, so it is necessary to switch the database.
Let's switch and create with the following command.
//Database switching
MariaDB [(none)]> use sampleapi_development;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
MariaDB [sampleapi_development]> CREATE TABLE users (
-> id int NOT NULL AUTO_INCREMENT,
-> name varchar(255) NOT NULL,
-> email varchar(255) NOT NULL,
-> PRIMARY KEY (id)
-> );
Query OK, 0 rows affected (0.02 sec)
MariaDB [sampleapi_development]> INSERT INTO users(id, name, email) VALUES(1, 'ishii', '[email protected]');
Query OK, 1 row affected (0.01 sec)
Since it is easier to understand if there is data, I added it with an INSERT statement.
Now that the contents have been created, let's start the app. Open STS and right click on the project. Run as → Spring Boot App Let's start.
Check if the API is working.
$ curl localhost:8080/api/users
[{"id":1,"name":"ishii","email":"[email protected]"}]
You can get it properly
I will add a user
$ curl -XPOST -H "Content-Type:application/json" http://localhost:8080/api/users -d '{
"name":"ishii2","email":"[email protected]"
}'
{"id":2,"name":"ishii2","email":"[email protected]"}
No problem!
By the way, how to drop docker
$ docker-compose down
You can drop it by doing. It is recommended to drop docker properly after playing.
When it comes to databases, I think it's really better to use migration. However, this time I am trying to create data directly because I was not able to chase so much and the article became bloated. I wish I could write around here as well.
・ API construction https://ishiis.net/2016/09/08/spring-boot-rest-api/ ・ Docker https://qiita.com/ken0909/items/a3f8594ce677bbc7c4c2 ・ Access the DB in the docker app https://qiita.com/M_Nagata/items/120831bb4e4a3deace13
The above is how to make an API with Docker + Spring that I made and saw. It's an ugly article, but thank you for watching it to the end. I'm currently studying rails, so I hope I can write an article about it in the future.
Recommended Posts