Skip to content

Containerizing an app

Rodrigo edited this page Oct 16, 2019 · 2 revisions

This page is about the process of containerizing a simple container. There are some examples on docker-vagrant repository, in this particular case, we are going to build a Golang app.

vagrant@ubuntu-xenial:~$ git clone https://github.com/rdrgporto/docker-vagrant.git
Cloning into 'docker-vagrant'...
remote: Enumerating objects: 29, done.
remote: Counting objects: 100% (29/29), done.
remote: Compressing objects: 100% (18/18), done.
remote: Total 29 (delta 5), reused 29 (delta 5), pack-reused 0
Unpacking objects: 100% (29/29), done.
Checking connectivity... done.
    
vagrant@ubuntu-xenial:~$ cd docker-vagrant/dockerfiles/golang/

vagrant@ubuntu-xenial:~/docker-vagrant/dockerfiles/golang$ ls
code  Dockerfile

I have added comments for every instruction on Dockerfile:

# We specify the base image we need for our go application
FROM golang:1.12.10 as builder

# We specify Dockerfile's maintener
LABEL maintainer="Rodrigo Porto <https://github.com/rdrgporto>"

# Information about app port
EXPOSE 9000

# Set the current working directory inside the container
WORKDIR /app

# Copy our code to /app
COPY code ./

# Build binary
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .

# We use alipine in order to reduce image size
FROM alpine:3.10

# Create app-user (-D Don't assign a password -g Account information)
RUN adduser -D -g '' app-user

# Set the current working directory inside container
WORKDIR /usr/share/app-go

# Copy our binary from builder stage
COPY --from=builder /app/main .

# Set folder permissions
RUN chown -R app-user:app-user /usr/share/app-go

# Use an unprivileged user
USER app-user

# Run our app
CMD ["/usr/share/app-go/main"]

The following command will build a new image called app-go:latest. The dot (.) at the end of the command tells Docker to use the current working directory. If you not specify a Tag, Docker will assume Tag=latest.

vagrant@ubuntu-xenial:~/docker-vagrant/dockerfiles/golang$ docker image build -t app-go:latest .
Sending build context to Docker daemon  4.096kB
Step 1/13 : FROM golang:1.12.10 as builder
1.12.10: Pulling from library/golang
4a56a430b2ba: Pull complete 
4b5cacb629f5: Pull complete 
14408c8d4f9a: Pull complete 
ea67eaa7dd42: Pull complete 
a2a2197e145e: Pull complete 
33b8ad332cc6: Pull complete 
aa30e10913db: Pull complete 
Digest: sha256:61152d6f60bd8d83e6f652bb99544cd0dae96945318a355d32f4cafaa2a5dc39
Status: Downloaded newer image for golang:1.12.10
 ---> f945ea07f224
Step 2/13 : LABEL maintainer="Rodrigo Porto <https://github.com/rdrgporto>"
 ---> Running in 8e3d95894a3e
Removing intermediate container 8e3d95894a3e
 ---> 3930bd6a2483
Step 3/13 : EXPOSE 9000
 ---> Running in 1a8824af9992
Removing intermediate container 1a8824af9992
 ---> bd99d6033558
Step 4/13 : WORKDIR /app
 ---> Running in 9c09de6c7d5d
Removing intermediate container 9c09de6c7d5d
 ---> 3e6673b5b212
Step 5/13 : COPY code ./
 ---> dc87374ff63c
Step 6/13 : RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .
 ---> Running in 821fe3f60a2b
Removing intermediate container 821fe3f60a2b
 ---> 51d7e7722ddc
Step 7/13 : FROM alpine:3.10
3.10: Pulling from library/alpine
9d48c3bd43c5: Pull complete 
Digest: sha256:72c42ed48c3a2db31b7dafe17d275b634664a708d901ec9fd57b1529280f01fb
Status: Downloaded newer image for alpine:3.10
 ---> 961769676411
Step 8/13 : RUN adduser -D -g '' app-user
 ---> Running in 7d18f938ae67
Removing intermediate container 7d18f938ae67
 ---> f33492945544
Step 9/13 : WORKDIR /usr/share/app-go
 ---> Running in 9bf1398a7fae
Removing intermediate container 9bf1398a7fae
 ---> 73698682d0d6
Step 10/13 : COPY --from=builder /app/main .
 ---> c39f6872011f
Step 11/13 : RUN chown -R app-user:app-user /usr/share/app-go
 ---> Running in 59b8de897461
Removing intermediate container 59b8de897461
 ---> d93a6c758527
Step 12/13 : USER app-user
 ---> Running in ab7e9c384b64
Removing intermediate container ab7e9c384b64
 ---> 18ccf86b97ca
Step 13/13 : CMD ["/usr/share/app-go/main"]
 ---> Running in 60012f2b27cb
Removing intermediate container 60012f2b27cb
 ---> 0e00c4b4d92a
Successfully built 0e00c4b4d92a
Successfully tagged app-go:latest

We can verify that our image has been created by docker image ls:

vagrant@ubuntu-xenial:~/docker-vagrant/dockerfiles/golang$ docker image ls 
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
app-go              latest              0e00c4b4d92a        2 minutes ago       20.2MB
<none>              <none>              51d7e7722ddc        2 minutes ago       846MB --> Dangling image
golang              1.12.10             f945ea07f224        3 days ago          814MB
alpine              3.10                961769676411        5 weeks ago         5.58MB

A dangling image is an image that is no anymore tagged. In this case, we have used a multi-stage build where we have started with golang:1.12.10 image (FROM golang:1.12.10 as builder) and in the process of building, we have changed to alpine:3.10 (FROM alpine:3.10) in order to reduce image size.

Having done that, the next step is push app-go image to Docker Hub. ⚠️ You need a Docker Hub account to be able to login, however, if you don't want to create a Docker Hub account with your private email, you can use a temporary email to do the practice.

vagrant@ubuntu-xenial:~/docker-vagrant/dockerfiles/golang$ docker login
Username:
Password:
Login Succeeded

Docker assumes Registry=docker.io and Tag=latest when we push our image to Docker Hub. However, Docker does not have a default value for the Repository, so that, you need to specify your repository.

¿ What is ? It is your account name on Docker Hub.

In my case is rdrg:

vagrant@ubuntu-xenial:~$ docker image ls 
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
app-go              latest              0e00c4b4d92a        35 minutes ago      20.2MB
<none>              <none>              51d7e7722ddc        35 minutes ago      846MB
golang              1.12.10             f945ea07f224        3 days ago          814MB
alpine              3.10                961769676411        5 weeks ago         5.58MB

vagrant@ubuntu-xenial:~$ docker image tag app-go:latest rdrg/app-go:0.0.1

vagrant@ubuntu-xenial:~$ docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
rdrg/app-go         0.0.1               0e00c4b4d92a        35 minutes ago      20.2MB
app-go              latest              0e00c4b4d92a        35 minutes ago      20.2MB
<none>              <none>              51d7e7722ddc        35 minutes ago      846MB
golang              1.12.10             f945ea07f224        3 days ago          814MB
alpine              3.10                961769676411        5 weeks ago         5.58MB

vagrant@ubuntu-xenial:~$ docker image push rdrg/app-go:0.0.1
The push refers to repository [docker.io/rdrg/app-go]
649f631572c0: Pushed 
2f7f43781e49: Pushed 
f80fd2069c02: Pushed 
632cceed7b95: Pushed 
03901b4a2ea8: Mounted from library/alpine 
0.0.1: digest: sha256:4931ab787dcd6f58a990b745bbeb8e4b3f4b9d7079dcf1306ed6b0af685bc2e3 size: 1365

It is time to run our app-go from Docker Hub:

vagrant@ubuntu-xenial:~$ docker container run -d --name app-go -p 8080:9000 rdrg/app-go:0.0.1 
b8a43465b3a3639c2b69034f49a093d0dca6af69e4c9264dc5bba2e997993860

vagrant@ubuntu-xenial:~$ curl localhost:8080
Welcome to my website!
Clone this wiki locally