Docker basics

Docker basics

Publish Date: Apr 1 '20
6 0

I'm here to share and well as to note some basics about Docker.
I'm Java developer, so I will mapping the concept from Java to Docker. If something confused you, please add comment and I will answer/update accordingly.

Terms

Docker Machine

The host/machine which is run docker server.
If you run Docker on Mac you will have a Virtual Machine which is, in this case, a Docker Machine

Image

Similar to Java, you packaged your app into Jar/War file and then your server will run it.
Similar to Docker, Image is a type of package that contains all of your things extras some OS files (/usr/bin, etc...).

Container

From Java point, you have Jar/War file, then you run it by java -jar your-jar.jar. The Java Runtime will starting to run your bytecode and you have a process.
Same for Docker, when you type docker run your-image, the docker runtime (currently default is runc) will start to run your image and create a process, which is, in docker terms - container.

Tag

Tagging or Versioning is always important.
When I was using Java, I just created my Jar/War and then Upload it to repository, say, version 1.0.0-RELEASE then the Ops guys will download that file from Repository and Run it.
In Docker, I have an image, I tag it, and then I push it into repository.
Tag is just the old wine in new bottle.

Volume

In Java, most of the time you will read/write file directly on Host Machine/Server and usually, that file will remain until you delete it.
In Docker, every time start a new container, the file system is fresh, none of your files from previous session will remain. This is a so-called "immutable". To solve that problem, Docker have a concept called volume.
To bind a volume inside Docker, simply add option --volume or -v for short.

Frequency used commands

docker run

Start a container

$ docker run --rm -it -P -v /tmp:/tmp/host ubuntu:18.04

In above command:
--rm mean: after this container finish execute, clean it!
it mean: Interactive shell. Without this, if your application require you to input, you cannot do it.
-P mean: If this container EXPOSE ports, please expose all of those ports randomly on DockerMachine. To bind specific port, 1323 for example. -p 11323:1323. Where 11323 is the port on Host Machine, and 1323 is port expose by container.
-v /tmp:/tmp/host mean: bind "/tmp" from host volume to "/tmp/host" in container.
Other useful options:
-d: Run container in detached mode. You shell will be freed immediately
--name: Name your container, then use can interact with its.

docker logs

$ docker run --name my-nginx --rm -p 38080:80 -d nginx:latest

Then curl 127.0.0.1:38080

Finally, to see access log of Nginx. docker logs my-nginx
Above command will print full logs of my-nginx container. To limit and follow limited line of logs, use docker logs --follow --tail 10 my-nginx

docker exec

$ docker exec -it my-nginx /bin/bash

This command is very useful to debug our code.
"Is my code created file as I expected?"
"How do I know if my code have all it dependencies? ldd my-binary!"
Using docker exec give you the same power as ssh to your server.

docker pull

$ docker pull containous/whoami

Will download containous/whoami:latest image to your machine.
To break down docker run, like we do in git.
git clone = git init + git remote add + git pull
docker run = docker pull + docker container create + docker container start

After testing and learning, now it's time to create our own docker image.

docker build

Here my file template for almost every project (Golang)

ARG BASE_IMAGE=gcr.io/distroless/base
FROM golang:1.14 as builder
COPY . /work
WORKDIR /work

RUN CGO_ENABLED=0 go build -a -ldflags '-extldflags "-static"' -o app main.go


FROM $BASE_IMAGE
LABEL maintainer="contact@liemlhd.com"
# Copy Built App
COPY --from=builder --chown=65532:65532 /work/app /app/app
USER nonroot
WORKDIR /app

EXPOSE 1323

ENTRYPOINT ["./app"]

And then

$ # To build production image
$ docker build -t saboteurkid/go-demo:latest -f Dockerfile .
$ # To build test/dev image
$ docker build -t saboteurkid/go-demo:latest-debug \
 --build-arg BASE_IMAGE=saboteurkid/ubuntu:18.04-base \
 -f Dockerfile .

docker push

Finally, Push you Image to the Repository

$ docker push saboteurkid/go-demo:latest
$ docker push saboteurkid/go-demo:latest-debug 

Some others useful commands:

docker tag: this is useful when you want to rename a tag to difference name. Say I want to fork a saboteurkid/go-demo:1.0.0 version from saboteurkid/go-demo:latest. Simply type:

$ docker tag saboteurkid/go-demo:latest saboteurkid/go-demo:1.0.0

docker commit: this is useful when you want to commit your changes after add some changes to your container. Example:

$ docker exec my-nginx cp /etc/hosts /tmp/hosts
$ docker commit my-nginx saboteurkid/nginx-with-text-file
$ docker run --rm -it -d --name nginx-with-file saboteurkid/nginx-with-text-file
$ docker exec nginx-with-file cat /tmp/file.txt | head -n1 
$ # Will show: `127.0.0.1 localhost`

Comments 0 total

    Add comment