NodeJS application:
# cat index.js const os = require('os'); const http = require('http'); const requestHandler = (req, res) => { console.log('Request incoming from ' + req.connection.remoteAddress); res.writeHead(200); res.end('Success! You\'ve hit ' + os.hostname() + ' on ' + os.platform() + '!'); }; const server = http.createServer(requestHandler) server.listen(3000);
Dockerfile
FROM node:lts ADD index.js /index.js CMD node index.js
Building image:
docker build -t nodejsapp .
Checking that image is available:
# docker images -a REPOSITORY TAG IMAGE ID CREATED SIZE nodejsapp latest 114a56ed7a9e 19 minutes ago 916MB none none 2518ebc2685a 19 minutes ago 916MB node lts 0cb3eeeded20 3 days ago 916MB
Building Container:
# docker run -d -p3000:3000 nodejsapp 1ab9de527ff5eaf79d3e555287287ea4e837513f9d4245a0c5f17cbb3c89fe3e
-d (detach) Starts the container in the background.
-it Run an image in interactive mode with the command /bin/bash
Checking that
docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1ab9de527ff5 nodejsapp "docker-entrypoint.s…" 23 seconds ago Up 21 seconds 0.0.0.0:3000->3000/tcp frosty
Can run multiple containers from one image on different ports
docker run -d -p3001:3000 nodejsapp docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 971bda49b10d nodejsapp "docker-entrypoint.s…" 39 seconds ago Up 37 seconds 0.0.0.0:3001->3000/tcp nostalgic 1ab9de527ff5 nodejsapp docker-entrypoint.s…" 2 minutes ago Up 2 minutes 0.0.0.0:3000->3000/tcp frosty
Please note size of the image:
# docker images -a REPOSITORY TAG IMAGE ID CREATED SIZE nodejsapp latest 114a56ed7a9e 32 minutes ago 916MB none none 2518ebc2685a 32 minutes ago 916MB node lts 0cb3eeeded20 3 days ago 916MB
go hello word
cat hello.go
package main import ( "fmt" "log" "net/http" ) // HelloServer responds to requests with the given URL path. func HelloServer(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, you requested: %s", r.URL.Path) log.Printf("Received request for path: %s", r.URL.Path) } func main() { var addr string = ":8180" handler := http.HandlerFunc(HelloServer) if err := http.ListenAndServe(addr, handler); err != nil { log.Fatalf("Could not listen on port %s %v", addr, err) } }
cat Dockerfile
FROM golang:1-alpine as build WORKDIR /app COPY ./ cmd RUN go build cmd/hello.go FROM alpine:latest WORKDIR /app COPY --from=build /app/hello /app/hello EXPOSE 8180 ENTRYPOINT ["./hello"]
docker build -t goapp .
docker images REPOSITORY TAG IMAGE ID CREATED SIZE goapp latest 2ba47decdb30 26 seconds ago 13MB nodejsapp latest 114a56ed7a9e 56 minutes ago 916MB node lts 0cb3eeeded20 3 days ago 916MB golang 1-alpine e1fd9820be16 9 days ago 359MB alpine latest e7d92cdc71fe 5 weeks ago 5.59MB
docker run -d -p3003:8180 goapp
# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5d5de4bf87da goapp "./hello" 8 seconds ago Up 6 seconds 0.0.0.0:3003->8180/tcp boring 971bda49b10d nodejsapp "docker-entrypoint.s…" 28 minutes ago Up 28 minutes 0.0.0.0:3001->3000/tcp nostalgic 1ab9de527ff5 nodejsapp "docker-entrypoint.s…" 30 minutes ago Up 30 minutes 0.0.0.0:3000->3000/tcp frosty
Drastically reduce the size of your DOCKER images with MULTISTAGE builds
Links:
Anti-Patterns When Building Container Images
Jason Hall explains in particular how to build and push images containing Go programs efficiently and securely. Spoilers: it’s specific to Go (because Go has an outstanding toolchain), but even if you want to containerize other languages, it’s a good read, I promise:
Moving and Building Container Images, The Right Way