この記事はリクルートライフスタイル Advent Calendar 2018の25日目の記事です。
はじめに
みなさんは新しい言語を習得していく時の最初の一歩はHello World
ではないでしょうか? この記事で単なるHello World
を出力ではなく、Hello World
ウェッブサーバーをいくつかのプログラミング言語で作って行きたいと思います。各言語のウェッブサーバーフレームワークを使用せずに、できるだけ標準ライブラリーを使用します。
あ、本日は12月25日Christmas Dayということで、Hello World
の代わりにMerry Christmas!
というメッセージを表示するようにしました。
また、ローカルマシンではそれぞれの言語をインストールのはめんどくさいと思うので、Docker Imageを使ってcontainer上で実行します。
Dockerfileとソースコードがあるディレクターで以下のコマンドを実行します。
docker build --tag server-xmas:latest . && docker run --rm -p 8080:8080 server-xmas:latest
プラウザで localhost:8080 に開くと、Merry Christmas!
というメッセージが表示されます。
では、各言語の書きやすさなどを比べてみてくださいね。
みなさん、Merry Christmas!!!
Go
以下のように、ソースコードとDockerfileを配置し、上記でのdockerコマンドを実行します。
├── Dockerfile
└── xmas
└── main.go
ソースコード
main.go
:
package main
import (
"fmt"
"log"
"net/http"
)
var greeting = "Merry Christmas! (go)"
func myHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, greeting)
}
func main() {
http.HandleFunc("/", myHandler)
log.Fatal(http.ListenAndServe(":8080", nil))
}
Dockerfile
FROM golang:1.8-alpine
COPY xmas /go/src/xmas
RUN go install xmas
FROM alpine:latest
COPY --from=0 /go/bin/xmas .
EXPOSE 8080
CMD ./xmas
Python
python3の実装です。以下のように、ソースコードとDockerfileを配置し、上記でのdockerコマンドを実行します。
.
├── Dockerfile
├── main.py
ソースコード
main.py
:
import http.server
import socketserver
GREETING = "Merry Christmas! (python3)"
class MyHandler(http.server.SimpleHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.end_headers()
self.wfile.write(bytes(GREETING, "utf-8"))
with socketserver.TCPServer(("", 8080), MyHandler) as httpd:
print("Server Running...")
httpd.serve_forever()
Dockerfile
FROM python:3.7-alpine
ENV DIR=/work
COPY main.py ${DIR}/main.py
WORKDIR ${DIR}
EXPOSE 8080
CMD python main.py
Java
javaのウェッブサーバーと言えば、Spring
を使うと思いますが、メッセージ表示するだけなので標準のライブラリーだけで作成します。
以下のように、ソースコードとDockerfileを配置し、上記でのdockerコマンドを実行します。
.
├── Dockerfile
├── main.java
ソースコード
main.java
:
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
class Main {
static final String GREETING = "Merry Christmas! (java)";
public static void main (String args[]) throws IOException {
HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0);
server.createContext("/", new MyHandler());
server.setExecutor(null);
server.start();
}
static class MyHandler implements HttpHandler {
public void handle(HttpExchange t) throws IOException {
System.out.println("Server running...");
t.sendResponseHeaders(200, GREETING.length());
OutputStream outputStream = t.getResponseBody();
outputStream.write(GREETING.getBytes());
outputStream.close();
}
}
}
Dockerfile
FROM openjdk:8-jdk-alpine3.8
ENV DIR=/work
COPY main.java ${DIR}/main.java
WORKDIR ${DIR}
RUN javac main.java
EXPOSE 8080
CMD java Main
NodeJs
なまのJavascriptでは書けないので、nodejsで書きます!
以下のように、ソースコードとDockerfileを配置し、上記でのdockerコマンドを実行します。
.
├── Dockerfile
├── main.js
ソースコード
main.js
:
const http = require('http');
const port = 8080;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Merry Christmas! (nodejs)\n');
});
server.listen(port, () => {
console.log(`Server running at http://localhost:${port}/`);
});
Dockerfile
FROM node:8.14-alpine
ENV DIR=/work
COPY main.js ${DIR}/main.js
WORKDIR ${DIR}
EXPOSE 8080
CMD node main.js
Ruby
以下のように、ソースコードとDockerfileを配置し、上記でのdockerコマンドを実行します。
.
├── Dockerfile
├── main.rb
ソースコード
main.rb
:
const http = require('http');
require 'socket'
message = "Merry Christmas! (ruby)"
server = TCPServer.new 8080
loop do
client = server.accept
client.puts "HTTP/1.0 200 OK"
client.puts "Content-Type: text/plain"
client.puts
client.puts message
client.close
end
Dockerfile
FROM ruby:2.5-alpine
ENV DIR=/work
COPY main.rb ${DIR}/main.rb
WORKDIR ${DIR}
EXPOSE 8080
CMD ruby main.rb
##おわりに
上記を比べてみてどうでしょうか? それぞれの良さがちょっとだけでも見えたら幸いです。
次の記事では各言語の主要となるフレームワークを使って、 Hello World!
ウェッブサーバーも作って行こうと思います。
ソースコードもGithubに上げています。