Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build the binaries with static linking and without CGO. #34

Merged
merged 2 commits into from
Jun 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 43 additions & 38 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,74 +5,79 @@

# Builder container builds the demo programs for named entities
# recognition (ner-server), model importing (hugging_face_importer),
# and question answering (bert_server). The binaries are copied into
# the same runtime container below. The version of Go given in the
# image tag must match the version of Go in go.mod.
# and question answering (bert_server). The binaries are then copied
# into the same runtime container below. The version of Go given in
# the image tag must match the version of Go in go.mod. The binaries
# have all been statically linked, and they were built without cgo.
FROM golang:1.14-alpine as Builder

# Some of the Go packages used by spaGo require gcc.
# Some of the Go packages used by spaGo require gcc. OpenSSL is used
# to generate a self-signed cert in order to test the Docker image.
# The packages ca-certificates is needed in order to run the servers
# using TLS.
RUN set -eux; \
apk add --no-cache --virtual .build-deps \
ca-certificates \
gcc \
musl-dev \
openssl \
;

# The spago user is created so that the servers can be run
# with limited privileges.
RUN adduser -S spago

# Build statically linked Go binaries without CGO.
RUN mkdir /build
ADD . /build/
WORKDIR /build
RUN go mod download
RUN GOOS=linux GOARCH=amd64 go build -o ner-server cmd/ner/main.go
RUN GOOS=linux GOARCH=amd64 go build -o hugging_face_importer cmd/huggingfaceimporter/main.go
RUN GOOS=linux GOARCH=amd64 go build -o bert_server cmd/bert/main.go


# The definition of the runtime container now follows, and it contains
# demo programs for named entities recognition (ner-server), model
# importing (hugging_face_importer), and question answering
# (bert_server). The version of Alpine given in the image tag should
# match the version of Alpine used in the Builder image.
FROM alpine:3.12

# The packages ca-certificates and openssl are needed in order to run
# the servers using TLS.
RUN apk add --no-cache \
ca-certificates \
openssl \
;

# The spago user and spago group are created so that the servers can
# be run with limited privileges.
RUN addgroup -S spago && adduser -S spago -G spago
RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags="-extldflags=-static" -o bert_server cmd/bert/main.go
RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags="-extldflags=-static" -o hugging_face_importer cmd/huggingfaceimporter/main.go
RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags="-extldflags=-static" -o ner-server cmd/ner/main.go
RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags="-extldflags=-static" -o docker-entrypoint docker-entrypoint.go

# A self-signed certificate and private key is generated so that the
# servers can easily support TLS without requiring the user to
# generate their own certificates.
RUN mkdir /etc/ssl/certs/spago ;\
openssl req \
RUN mkdir /etc/ssl/certs/spago \
&& openssl req \
-x509 \
-nodes \
-newkey rsa:2048 \
-keyout /etc/ssl/certs/spago/server.key \
-out /etc/ssl/certs/spago/server.crt \
-days 3650 \
-subj "/C=IT/ST=Piedmont/L=Torino/EA=matteogrella@gmail.com/CN=*" && \
chgrp spago /etc/ssl/certs/spago/server.key && \
chmod 0640 /etc/ssl/certs/spago/server.key \
-subj "/C=IT/ST=Piedmont/L=Torino/O=NLP Odyssey/OU=spaGo/emailAddress=matteogrella@gmail.com/CN=*" \
&& chmod +r /etc/ssl/certs/spago/server.key \
;

# Copy the script docker-entrypoint.sh from source.
COPY --chown=spago:spago docker-entrypoint.sh /home/spago/
RUN chmod 0755 /home/spago/docker-entrypoint.sh

# The definition of the runtime container now follows, and it contains
# demo programs for named entities recognition (ner-server), model
# importing (hugging_face_importer), and question answering
# (bert_server).
FROM scratch

# Copy the user info from the Builder container.
COPY --from=Builder /etc/passwd /etc/passwd
USER spago

# Copy the CA certs and the self-signed cert.
COPY --from=Builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY --from=Builder /etc/ssl/certs/spago/server.crt /etc/ssl/certs/spago/server.crt
COPY --from=Builder /etc/ssl/certs/spago/server.key /etc/ssl/certs/spago/server.key

# Copy the compiled demo servers and other programs from the Builder
# container.
COPY --chown=spago:spago --from=Builder /build/* /home/spago/
COPY --from=Builder /build/bert_server /bert_server
COPY --from=Builder /build/hugging_face_importer /hugging_face_importer
COPY --from=Builder /build/ner-server /ner-server
COPY --from=Builder /build/docker-entrypoint /docker-entrypoint

# Setup the environment and run the script docker-entrypoint.sh so
# that a help screen is printed to the user when no commands are given.
ENV GOOS linux
ENV GOARCH amd64
USER spago
WORKDIR /home/spago
ENTRYPOINT ["/home/spago/docker-entrypoint.sh"]
ENTRYPOINT ["/docker-entrypoint"]
CMD ["help"]
57 changes: 57 additions & 0 deletions docker-entrypoint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright 2020 spaGO Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
"fmt"
"os"
"os/exec"
"strings"
"syscall"
)

const (
help = `
spaGO is a beautiful and maintainable machine learning library written in Go designed to support relevant neural network architectures in natural language processing tasks.

Usage:
<command> [arguments]

The commands are:

bert_server demo server for question answering
hugging_face_importer demo program for model importing
ner-server demo server for named entities recognition

See README.md for more information about run the demo servers using docker.
`
)

// The script docker-entrypoint.sh wraps access to the demo
// programs for named entities recognition (ner-server), model
// importing (hugging_face_importer), and question answering
// (bert_server).
func main() {

// The help screen is printed to the user when no commands
// are given, or when the command "help" is given.
if len(os.Args) == 1 || strings.EqualFold(os.Args[1], "help") {
fmt.Println(help)
os.Exit(0)
}

// Run the commands defined by the Dockerfile CMD directive or overrides.
proc := os.Args[1]
_, err := exec.LookPath(proc)
if err != nil {
panic(err)
}

args := os.Args[1:]
fmt.Printf("Running command: '%s'\n", strings.Join(args, " "))
if err := syscall.Exec(proc, args, os.Environ()); err != nil {
panic(err)
}
}
38 changes: 0 additions & 38 deletions docker-entrypoint.sh

This file was deleted.