github.com/emc-advanced-dev/unik@v0.0.0-20190717152701-a58d3e8e33b7/docs/getting_started_java.md (about) 1 # Getting Started: OSv on Java Edition! 2 3 In this tutorial we'll be: 4 1. [installing UniK](getting_started_java.md#installing-unik) 5 2. [writing a simple HTTP Daemon in Java](getting_started_java.md#write-a-java-http-server-using-maven) 6 3. [compiling to a unikernel and launching an instance on Virtualbox](getting_started_java.md#compile-an-image-and-run-on-virtualbox) 7 8 ### Installing UniK 9 #### Prerequisites 10 Ensure that each of the following are installed 11 - [Docker](http://www.docker.com/) installed and running with at least 4GB available space for building images 12 - [`jq`](https://stedolan.github.io/jq/) 13 - [`make`](https://www.gnu.org/software/make/) 14 - [Virtualbox](https://www.virtualbox.org/) 15 - [Maven](https://maven.apache.org/download.cgi) 16 17 #### Install, configure, and launch UniK 18 1. Install UniK 19 ``` 20 $ git clone https://github.com/solo-io/unik.git 21 $ cd unik 22 $ make 23 ``` 24 note: `make` will take quite a few minutes the first time it runs. the UniK `Makefile` is pulling all of the Docker images that bundle UniK's dependencies. 25 26 Then, place the `unik` executable in your `$PATH` to make running UniK commands easier: 27 ``` 28 $ mv _build/unik /usr/local/bin/ 29 ``` 30 31 2. Configure a Host-Only Network on Virtualbox 32 * Open Virtualbox 33 * Open **Preferences** > **Network** > **Host-only Networks** 34 * Click the green add button on the right side of the UI 35 * Record the name of the new Host-Only adapter. You will need this in your UniK configuration 36 * Ensure that the Virtualbox DHCP Server is Enabled for this Host-Only Network: 37 * With the Host-Only Network selected, Click the edit button (screwdriver image) 38 * In the **Adapter** tab, note the IPv4 address and netmask of the adapter. 39 * In the **DHCP Server** tab, check the **Enable Server** box 40 * Set **Server Address** an IP on the same subnet as the Adapter IP. For example, if the adapter IP is `192.168.100.1`, make set the DHCP server IP as `192.168.100.X`, where X is a number between 2-254. 41 * Set **Server Mask** to the netmask you just noted 42 * Set **Upper / Lower Address Bound** to a range of IPs on the same subnet. We recommend using the range `X-254` where X is one higher than the IP you used for the DHCP server itself. E.g., if your DHCP server is `192.168.100.2`, you can set the lower and upper bounds to `192.168.100.3` and `192.168.100.254`, respectively. 43 44 3. Configure UniK daemon 45 * Using a text editor, create and save the following to `$HOME/.unik/daemon-config.yaml`: 46 47 ```yaml 48 providers: 49 virtualbox: 50 - name: my-vbox 51 adapter_type: host_only 52 adapter_name: NEW_HOST_ONLY_ADAPTER 53 ``` 54 55 replacing `NEW_HOST_ONLY_ADAPTER` with the name of the network adapter you created. 56 57 4. Launch UniK and automatically deploy the *Virtualbox Instance Listener* 58 * Open a new terminal window/tab. This terminal will be where we leave the UniK daemon running. 59 * `cd` to the `_build` directory created by `make` 60 * run `./unik daemon --debug` (the `--debug` flag is optional, if you want to see more verbose output) 61 * UniK will compile and deploy its own 30 MB unikernel. This unikernel is the [Unik Instance Listener](./instance_listener.md). The instance listener uses udp broadcast to detect instance ips and bootstrap instances running on Virtualbox. 62 * After this is finished, UniK is running and ready to accept commands. 63 * Open a new terminal window and type `unik target --host localhost` to set the CLI target to the your local machine. 64 65 --- 66 67 #### Write a Java HTTP server using Maven 68 0. Open a new terminal window, but leave the window with the daemon running. This window will be used for running UniK CLI commands. 69 1. `mkdir` a new directory to create this sample app in & `cd` to it. 70 2. Generate a new maven project with the following command: 71 72 ``` 73 mvn -B archetype:generate \ 74 -DarchetypeGroupId=org.apache.maven.archetypes \ 75 -DgroupId=com.mycompany.app \ 76 -DartifactId=my-app 77 ``` 78 79 Great! we've got the project structure created. Let's `cd` into the new project folder `my-app`. 80 81 3. We need to add a plugin to our project's `pom.xml` so it can be built as a fat jar (all dependencies packaged into one `.jar` file): 82 * Add the `maven-assembly-plugin` between the `<plugins>...</plugins>` tags: 83 84 ```xml 85 <plugins> 86 <plugin> 87 <groupId>org.apache.maven.plugins</groupId> 88 <artifactId>maven-assembly-plugin</artifactId> 89 <version>2.2-beta-4</version> 90 <configuration> 91 <descriptorRefs> 92 <descriptorRef>jar-with-dependencies</descriptorRef> 93 </descriptorRefs> 94 <archive> 95 <manifest> 96 <mainClass>com.mycompany.app.App</mainClass> 97 </manifest> 98 </archive> 99 </configuration> 100 <executions> 101 <execution> 102 <phase>package</phase> 103 <goals> 104 <goal>single</goal> 105 </goals> 106 </execution> 107 </executions> 108 </plugin> 109 </plugins> 110 ``` 111 112 * Now our application is UniK-ready. Let's add some code to our `App.java` source file. Open up `src/main/java/com/mycompany/app/App.java` and replace its contents with the following: 113 114 ```java 115 package com.mycompany.app; 116 117 import java.io.IOException; 118 import java.io.OutputStream; 119 import java.net.InetSocketAddress; 120 121 import com.sun.net.httpserver.HttpExchange; 122 import com.sun.net.httpserver.HttpHandler; 123 import com.sun.net.httpserver.HttpServer; 124 125 public class App 126 { 127 public static void main(String[] args) throws Exception { 128 System.out.println("Started!"); 129 HttpServer server = HttpServer.create(new InetSocketAddress(4000), 0); 130 server.createContext("/", new MyHandler()); 131 server.setExecutor(null); // creates a default executor 132 server.start(); 133 } 134 135 static class MyHandler implements HttpHandler { 136 @Override 137 public void handle(HttpExchange t) throws IOException { 138 String response = "Java running inside a unikernel!"; 139 t.sendResponseHeaders(200, response.length()); 140 OutputStream os = t.getResponseBody(); 141 os.write(response.getBytes()); 142 os.close(); 143 } 144 } 145 } 146 ``` 147 148 2. If you have Java installed, you can try running this code with `mvn package && java -jar target/my-app-1.0-SNAPSHOT-jar-with-dependencies.jar`. Visit [http://localhost:4000/](http://localhost:4000/) to see that the server is running. 149 150 3. We have to add a manifest file to tell unik how to build our application into a unikernel. Create a file named `manifest.yaml` in the same directory as the `pom.xml` (the java project root) and paste the following inside: 151 152 ```yaml 153 main_file: target/my-app-1.0-SNAPSHOT-jar-with-dependencies.jar 154 build_command: mvn package 155 ``` 156 This will tell UniK to build our project with the `mvn package` commmand, and that the resulting jar file will be located at `target/my-app-1.0-SNAPSHOT-jar-with-dependencies.jar`. 157 158 4. Great! Now we're ready to compile this code to a unikernel. 159 160 --- 161 162 #### Compile an image and run on Virtualbox 163 164 1. Make sure that the UniK daemon is still running, and run the following: 165 ``` 166 unik build --name myJavaImage --path PATH_TO_JAVA_PROJECT --base osv --language java --provider virtualbox 167 ``` 168 Replacing `PATH_TO_JAVA_PROJECT` with the path to the root of the java project we created. (This will be the directory containing the `pom.xml` file). 169 2. You can watch the output of the `build` command in the terminal window running the daemon. 170 3. When `build` finishes, the resulting disk image will exist as a virtual disk image in your `$HOME/.unik` directory. 171 4. Run an instance of this image with 172 ``` 173 unik run --instanceName myJavaInstance --imageName myJavaImage 174 ``` 175 5. When the instance finishes launching, let's check its IP and see that it is running our application. 176 6. Run `unik instances`. The instance IP Address should be listed. 177 7. Direct your browser to `http://instance-ip:4000` and see that your instance is running! 178 8. To clean up your image and the instance you created 179 ``` 180 unik rmi --force --image myImage 181 ```