Skip to content

Commit

Permalink
Merge pull request #36 from darklynx/better_docker
Browse files Browse the repository at this point in the history
Better docker
  • Loading branch information
darklynx committed Jul 27, 2018
2 parents 0e557fb + 9fffb55 commit f9096bb
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 28 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
24 changes: 14 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ It is strongly inspired by ideas and application design of the [RequestHub](http
- [Screenshots](#screenshots)
- [Install](#install)
- [Build from source](#build-from-source)
- [Run](#run)
- [Run docker container](#run-docker-container)
- [Configuration](#configuration)
- [Parameters](#parameters)
- [Usage](#usage)
Expand Down Expand Up @@ -56,17 +56,26 @@ Configuration of basket responses:

### Build from source

Build latest:

```bash
$ go get github.com/darklynx/request-baskets
```

### Run
Run:

```bash
$ export PATH=$PATH:$GOPATH/bin
$ request-baskets
```

### Run docker container

```
$ docker pull darklynx/request-baskets
$ docker run -p 55555:55555 darklynx/request-baskets
```

## Configuration

Request Baskets service supports several command line configuration parameters. Use `-h` or `--help` to print command line help:
Expand Down Expand Up @@ -203,16 +212,11 @@ $ docker stop mysql_baskets
$ docker build -t request-baskets .
```

This will create a docker image based on `golang:onbuild` image with compiled version of request baskets service
ready to test. Size of built image is ~750 Mb.

To build minimalistic image based on `alpine` image (final size is ~15 Mb) simply run:
This will create a docker image using [multi-stage docker builds](https://docs.docker.com/develop/develop-images/multistage-build/) approach with 2 stages: compiling the service and packaging the result to a tiny alpine container. The resulting size of built image is ~12 Mb.

```bash
$ ./docker/minimal/build.sh
```
Note: since the first stage is using `golang:latest` container to build the service executable, there is no need to have Go lang SDK installed on the machine where process of building the container is taking place.

See [docker folder](./docker) for alternative docker builds.
See [docker folder](./docker) for alternative docker builds with detailed explanation of the process for every variant.

### Run container as a service

Expand Down
62 changes: 45 additions & 17 deletions docker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,40 @@
```bash
$ docker images

REPOSITORY TAG IMAGE ID CREATED SIZE
request-baskets golang 8fe4269dbc19 7 minutes ago 768.4 MB
request-baskets ubuntu 86d1c3b87154 53 seconds ago 378.8 MB
request-baskets alpine 7991c7cec214 6 minutes ago 15.2 MB
REPOSITORY TAG IMAGE ID CREATED SIZE
request-baskets multistage 969d4a6f4799 8 minutes ago 11.9MB
request-baskets minimal 91ee7e035488 15 seconds ago 15.9MB
request-baskets ubuntu cf2c7f5a5c75 3 minutes ago 155MB
request-baskets onbuild 31bc1924e99e 5 minutes ago 719MB
...
```

## Docker with "golang"
## Use "multistage" docker build

:warning: `ONBUILD` image variants are [deprecated](https://github.com/docker-library/official-images/issues/2076), and their use is discouraged.
Using a multi-stage docker builds is now considered to be the most efficient and [officially recommended](https://docs.docker.com/develop/develop-images/multistage-build/) way of building a minimalistic version of docker images for simple services or any other kinds of software.

This is an example of how to use a great [golang:onbuild](https://github.com/docker-library/docs/tree/master/golang) image from official Docker library for Go language.
In depth it is similar to the approach taken when building "minimal" version of docker container (see below), but instead of using an additional shell script to combine several steps (stages) it relies on the relatively new feature of Docker to describe all steps in a single [Dockerfile](./multistage/Dockerfile) and pass the result from one step to another using new syntax: `COPY --from=...`

Building an image that is based on `golang:onbuild` image should be triggered from the root folder of Go application. The source code from the current folder is copied into container and compiled inside. The result of compilation is packed into a new image with a command that launches the application. The content of [Dockerfile](./golang/Dockerfile) in this case is minimal.
This [Dockerfile](./multistage/Dockerfile) is designed to run from the root folder of service application. During the first stage (named `builder`) `golang:latest` docker container is used to compile the service with some tunings to minimize the size of resulting executable file. The second stage prepares "alpine" container and copies the service file from first stage into the new container, it also configures the default command to run when container is started.

To build the service image and launch an instance of container run following commands from the project root folder:

Usage example (should be started from source code root directory):
```bash
$ docker build -t request-baskets .
$ docker run -it --rm --name rbaskets -p 55555:55555 request-baskets
```
$ docker build -f docker/multistage/Dockerfile -t request-baskets .
$ docker run --rm --name rbaskets -d -p 55555:55555 request-baskets
2f5c3c236795c66324...

Now you can visit [http://localhost:55555](http://localhost:55555) in your browser.
$ docker logs rbaskets
2018/07/27 00:01:45 [info] generated master token: bShKSx57jbbEIUa...
2018/07/27 00:01:45 [info] using Bolt database to store baskets
2018/07/27 00:01:45 [info] Bolt database location: /var/lib/rbaskets/baskets.db
2018/07/27 00:01:45 [info] HTTP server is listening on 0.0.0.0:55555
```

To stop the service simply hit `Ctrl+C` - this will stop and delete the running container (note `--rm` flag).
Now you are ready to use the Request Baskets service locally, just open [http://localhost:55555](http://localhost:55555) in your browser.

Use of `golang:onbuild` image allows you to build and run Go applications without Go SDK being installed on your computer. However the Go SDK with all dependencies remains in the final image of built application, which results in really big image size (see above).

## Docker with "ubuntu"
## Use "ubuntu" docker build

This is an example of how to build and package Go application within container based on well known Linux server images. In this case the image is based on latest [ubuntu](https://github.com/docker-library/docs/tree/master/ubuntu) image from official Docker library.

Expand Down Expand Up @@ -74,7 +80,8 @@ $ docker start rbaskets

Note that `request-baskets` is configured to save data in Bolt database, hence the collected data is not lost after container restart. Database is placed on a volume that can be accessed from another containers for analyses or backup purposes.

## Docker with "minimal" (alpine)

## Use "minimal" docker build

Building minimalistic docker image with `request-baskets` service is spit in 2 steps:

Expand All @@ -92,3 +99,24 @@ Second step uses [Dockerfile](./minimal/Dockerfile) to build image based on simp
**Important:** since `alpine` image includes minimal to none dependencies to minimize the original image size the [static linking](http://www.blang.io/posts/2015-04_golang-alpine-build-golang-binaries-for-alpine-linux/) during Go compilation is a solution to build an executable that may run inside `alpine` container.

Similar to "ubuntu" Docker script this [Dockerfile](./minimal/Dockerfile) also declares a volume to expose the Bolt database location.


## Use "onbuild" docker build

:warning: `ONBUILD` image variants are [deprecated](https://github.com/docker-library/official-images/issues/2076), and their use is discouraged.

This is an example of how to use a former great [golang:onbuild](https://github.com/docker-library/docs/tree/master/golang) image from official Docker library for Go language.

Building an image that is based on `golang:onbuild` image should be triggered from the root folder of Go application. The source code from the current folder is copied into container and compiled inside. The result of compilation is packed into a new image with a command that launches the application. The content of [Dockerfile](./onbuild/Dockerfile) in this case is minimal.

Usage example (should be started from source code root directory):
```bash
$ docker build -f docker/onbuild/Dockerfile -t request-baskets .
$ docker run -it --rm --name rbaskets -p 55555:55555 request-baskets
```

Now you can visit [http://localhost:55555](http://localhost:55555) in your browser.

To stop the service simply hit `Ctrl+C` - this will stop and delete the running container (note `--rm` flag).

Use of `golang:onbuild` image allows you to build and run Go applications without Go SDK being installed on your computer. However the Go SDK with all dependencies remains in the final image of built application, which results in really big image size (see above).
3 changes: 3 additions & 0 deletions docker/minimal/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ MAINTAINER Vladimir L, vladimir_l@gmx.net
# Create a volume for request-baskets service data folder
VOLUME /var/lib/rbaskets

# Include CA certs for baskets that forward to https://...
RUN apk --no-cache add ca-certificates

# Copy built service
COPY request-baskets /usr/local/bin/

Expand Down
17 changes: 17 additions & 0 deletions docker/multistage/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Builds Request Baskets service using multi-stage builds
# Version 1.0

# Stage 1. Building service
FROM golang:latest as builder
WORKDIR /go/src/rbaskets
COPY . .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -installsuffix cgo -ldflags="-w -s" -o /go/bin/rbaskets

# Stage 2. Packaging into alpine
FROM alpine:latest
MAINTAINER Vladimir L, vladimir_l@gmx.net
RUN apk --no-cache add ca-certificates
VOLUME /var/lib/rbaskets
COPY --from=builder /go/bin/rbaskets /bin/rbaskets
EXPOSE 55555
CMD /bin/rbaskets -l 0.0.0.0 -db bolt -file /var/lib/rbaskets/baskets.db
File renamed without changes.

0 comments on commit f9096bb

Please sign in to comment.