📜 ⬆️ ⬇️

We collect Docker container with http server using Gradle

image Hi Habr!

There was such a task: Make a simple web - server with a minimum number of dependencies. At the same time it will be deployed in the form of a docker container. To implement the server itself, I will use GrizzlyWebServer . To build Gradle with a plugin for docker from Benjamin Muschko (bmuschko).

This choice of tools is not accidental, I am developing for android and Java is closer to me and Gradle than something else. In this article I want to describe in detail the process from writing an application to running in docker, possible problems and their solutions.
')
And so, let's start: the server.

Create a new Gradle project in IntelliJ IDEA.

image

image

An empty project has been created; we will add the HabrWebServer class with the main () method. Add the line to build.gradle in dependencies.

compile group: 'org.glassfish.grizzly', name: 'grizzly-http-server', version: '2.3.28' 

The code of our simplest server
 public class HabrWebServer { private static final Logger LOGGER = Grizzly.logger(HabrWebServer.class); public static void main(String[] args) { // create a basic server that listens 0.0.0.0:8080 final HttpServer server = HttpServer.createSimpleServer(); final ServerConfiguration config = server.getServerConfiguration(); // Map the path, '/', to the Handler config.addHttpHandler(new HabrHandler(), "/"); try { server.start(); System.out.println("The server is running. \nPress enter to stop..."); System.in.read(); } catch (IOException ioe) { LOGGER.log(Level.SEVERE, ioe.toString(), ioe); } finally { server.shutdownNow(); } } private static class HabrHandler extends HttpHandler { @Override public void service(Request request, Response response) throws Exception { response.setContentType("text/plain"); response.getWriter().write("Hello Habrahabr!"); } } } 


Open the console in the project directory type ./gradlew assemble - BUILD SUCCESSFUL.
Something we have already gathered.

But there is one unpleasant thing, in ide, imports do not work and server classics are highlighted in red.

image

It is treated this way - you need to find the magic refresh button and press it - Synchronizing Changes in Gradle Project and IntelliJ IDEA Project

Now we will launch the application locally, for this we use the 'application' plugin for Gradle .

Add the following lines to build.gradle:

 apply plugin: 'application' mainClassName = 'ru.test.HabrWebServer' 

Assemble and install the application:

  ./gradlew installDist 

Go to the folder / habrServer / build / install / habrServer / bin. Run the application:

 ./habrServer 

We open the browser, the server responds, but not by what we are waiting for.

image

It turns out that when creating a server, the createSimpleServer () method sets up first a handler that gives away static content of which we don’t have, and it doesn’t get to our handler. Change the server creation code.

  public static void main(String[] args) { final HttpServer server = createServer("0.0.0.0", 8080); ... } public static HttpServer createServer(String host, int port) { HttpServer server = new HttpServer(); NetworkListener listener = new NetworkListener("grizzly", host, new PortRange(port)); server.addListener(listener); return server; } 

It remains to build the application in the form of a docker container.
Let's start with the local docker installation .
After installing docker, the server listens only on a unix socket. Let's allow local access on tcp.

In the /lib/systemd/system/docker.service file we find and edit the line:

 ExecStart=/usr/bin/dockerd -H fd:// -H tcp://127.0.0.1:2375 

It is not entirely correct to change this file, since it changes the settings for all users, but in my case it is suitable for tests on my machine.

To collect the container we use bmuschko Gradle Docker plugin

Final build.gradle
 group 'habrServer' version '1.0-SNAPSHOT' apply plugin: 'java' apply plugin: 'application' apply plugin: 'com.bmuschko.docker-java-application' apply plugin: 'com.bmuschko.docker-remote-api' import com.bmuschko.gradle.docker.tasks.container.DockerCreateContainer mainClassName = 'ru.test.HabrWebServer' buildscript { repositories { jcenter() } dependencies { classpath 'com.bmuschko:gradle-docker-plugin:3.0.3' } } docker { url = 'http://127.0.0.1:2375' javaApplication { maintainer = 'Dmitry Barkalov "xxx@xxx.xxx"' ports = [8080] tag = 'habrwebserver' } } task createDocker(type: DockerCreateContainer) { dependsOn dockerBuildImage targetImageId { dockerBuildImage.getImageId() } portBindings = ['8080:8080'] } repositories { mavenCentral() jcenter() } dependencies { testCompile group: 'junit', name: 'junit', version: '4.11' compile group: 'org.glassfish.grizzly', name: 'grizzly-http-server', version: '2.3.28' } 


We assemble and install the container:

  ./gradlew createDocker 

image

Run!

image

Open in the browser.

image

Only one unresolved problem remained: the application waits in the main thread on System.in.read (); Therefore, we run docker with the -i option. ( Keep STDIN open even if not attached. ) Ie stdin remains attached to the container. You probably don’t need to make an application in the form of a demon; the docker can demonize himself. It is necessary to remove the interaction with stdin, and be able to stop the application. It remains to be learned. If someone knows write in the comments, I will be grateful.

Thank you for your attention, I hope the article was useful to someone.
Project ID on github.

Source: https://habr.com/ru/post/312724/


All Articles