Friday, 8 March 2019

Introduction to Docker

Docker is a platform which allows some application and all its dependencies to be packed in a container, shipped within this monolithic bundle and then deployed on any other machine with no fear that some dependency would be missing or not compatible with the new host.

Here are some terms:

host
  •  may be local or remote

container
  • process which runs on a host

Docker runs processes in isolated containers.

Lifecycle of Docker Container

Image Source and Credits: http://docker-saigon.github.io/post/Docker-Internals/

image

Docker images can consist of multiple layers. Layers can be reused by images. If a layer is downloaded as part of imageA and it is also part of imageB then when we pull/download imageB, this layer will not be downloaded again but will be reused.
  • image ID is a SHA256 digest covering the image’s configuration and layers. 


Dockerfile

Docker is a layered filesystem so every ADD, COPY and RUN instruction will create a new layer and cache it.
ADD
  • takes in a src and destination
  • lets you copying into the Docker image files/directories from following sources:
    • local file or directory from your host (the machine building the Docker image)
    • you can extract a local tar file from the source directly into the destination
    • URL
  • valid use case for ADD is when you want to extract a local tar file into a specific directory in your Docker image

ARG

  • defines a variable that users can pass at build-time to the builder with the docker build command using the --build-arg <varname>=<value> flag
  • Docker build will always show you the line as is written down in the Dockerfile, despite the variable value - ARG value will not be substituted in the terminal output. [ARG substitution in RUN command not working for Dockerfile]
  • Value of the argument provided in docker build command line will overwrite the (default) one set in Dockerfile.

Example:

Dockerfile:


ARG NPM_LOG_LEVEL=warn
RUN npm install --loglevel ${NPM_LOG_LEVEL}


Terminal:

$ docker build --pull --build-arg NPM_LOG_LEVEL=verbose -t my_app_image .



COPY

NOTE for ADD & COPY:
  • All new files and directories are created with a UID and GID of 0, unless the optional --chown flag specifies a given username, groupname, or UID/GID combination to request specific ownership of the content added.
  • Examples:
ADD --chown=someuser:somegroup /foo /bar 
COPY --chown=someuser:somegroup /foo /bar 
Or other combinations of user/group name (or ID); 
--chown=someuser:123 
--chown=anyuser:anygroup 
--chown=1001:1002 
--chown=333:agroupname


CMD
  • Lets you define a default command to run when your container starts
  • Executed in run-time;  does not execute anything at build time
  • Sets default command and/or parameters, which can be overwritten from command line when docker container runs
  • Has three forms:
    • Exec (preferred): CMD ["executable","param1","param2"]
    • ENTRYPOINT default parameters list: CMD ["param1","param2"]
    • Shell: CMD command param1 param2
  • Exec form executes stated executable and passes to it params listed.
  • Shell form invokes a command shell (e.g. sh -c) and passes both command (executable) and its params to it.
  • When used in the shell or exec formats, the CMD instruction sets the command to be executed when running the image.
  • If you would like your container to run the same executable every time, then you should consider using ENTRYPOINT in combination with CMD.
  • If the user specifies arguments to docker run then they will override the default specified in CMD.


ENTRYPOINT

  • Has two forms:
    • Exec (preferred): ENTRYPOINT ["executable", "param1", "param2"]
    • Shell: ENTRYPOINT command param1 param2
  • Exec form executes stated executable and passes to it params listed.
  • Shell form invokes a command shell (e.g. sh -c) and passes both command (executable) and its params to it.
  • Configures a container that will run as an executable. It should be used if container is intended to run the same executable every time. This means that we can pass arguments to the executable set as an entrypoint simply by listing them after the name of the container:          $ docker run ...<container_name> param1 param2...
  • Default values of arguments can be specified with CMD instruction in JSON array format: 
    • CMD ["param1", "param2"]
  • Executed in run-time
  • From Docker best practices:
The best use for ENTRYPOINT is to set the image’s main command, allowing that image to be run as though it was that command (and then use CMD as the default flags). 
Let’s start with an example of an image for the command line tool s3cmd: 
   ENTRYPOINT ["s3cmd"]
   CMD ["--help"] 
Now the image can be run like this to show the command’s help: 
   $ docker run s3cmd 
Or using the right parameters to execute a command: 
   $ docker run s3cmd ls s3://mybucket 
This is useful because the image name can double as a reference to the binary as shown in the command above.
Nice example of entrypoint.sh.

This is an example how can operator (person who is running container from an image) pass arguments to the executable run upon the container's launch:

Dockerfile:

...
ENTRYPOINT [ "/my-app" ]
CMD [ "--param1=arg1_default" ]

Launching the container:

$ docker run ... my-app-image --param1=arg1_value

arg1_value will overwrite param1's default value (arg1_default).

If --param1 is omitted then arg1_default will be applied to param1 which will be passed to my-app executable.


FROM


  • Set the baseImage to use for subsequent instructions
  • must be the first instruction in a Dockerfile.


FROM baseImage
FROM baseImage:tag
FROM baseImage@digest

If we don't want to use Docker Hub as Docker repository but some custom server, we can write:

FROM docker.example.com/image_name


LABEL

Set the name of the image author.
LABEL maintainer="author@example.com"

This info is shown in docker inspect output.


RUN

  • execute commands inside of Docker image
  • these commands get executed once at build time and get written into your Docker image as a new layer
  • often used for installing software packages
  • can be specified in two forms:
    • shell form, when it specifies arguments of /bin/sh -c 
      • e.g. RUN echo "test"
    • exec form, when it specifies an executable and list of its arguments
      • e.g. RUN ["/bin/my_app", "arg1", "arg2"]
  • it can be overridden by command specified withing docker run
Sometimes we need to replace some text in some file with some other. This is how to define default replacement string, how to perform replacement with sed and how to inject replacement string from docker build args:

Dockerfile:

ARG DOCKER_IMAGE_REGISTRY=docker.example.com
FROM ${DOCKER_IMAGE_REGISTRY}/golang:alpine as build
# If we add
#    RUN cat /etc/apk/repositories
# this will show that default apk package repositories are HTTP ones:
#    http://dl-cdn.alpinelinux.org/alpine/v3.10/main
#    http://dl-cdn.alpinelinux.org/alpine/v3.10/community
# We need to use some which supports HTTPS which can be found here:
#    https://github.com/alpinelinux/aports/blob/master/main/alpine-mirrors/mirrors.yaml
# Example:
#    If we set https://mirror.fit.cvut.cz/alpine/ via
#       RUN sed -i 's/http\:\/\/dl-cdn.alpinelinux.org/https\:\/\/mirror.fit.cvut.cz/g' /etc/apk/repositories
#    then registry will be:
#       https://mirror.fit.cvut.cz/alpine/v3.10/main
#       https://mirror.fit.cvut.cz/alpine/v3.10/community
# Use --build-arg in docker build to pass custom APK registry host. Example:
#    $ docker build --build-arg APK_PACKAGE_REGISTRY=mirror.fit.cvut.cz --no-cache --network host -t my-app .
ARG APK_PACKAGE_REGISTRY=apk.example.com/random/path/alpine-remote
RUN sed -i "s:http\:\/\/dl-cdn.alpinelinux.org:https\:\/\/${APK_PACKAGE_REGISTRY}:g" /etc/apk/repositories
RUN cat /etc/apk/repositories
RUN apk --no-cache add ca-certificates

# alpine contains /bin/sh so we can use it via
#    $ docker exec -it my-app sh
FROM ${DOCKER_IMAGE_REGISTRY}/alpine
LABEL maintainer="bojan.komazec@example.com"
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY ./bin/my-app /my-app
ENTRYPOINT [ "/my-app" ]
CMD [ "--param0=arg0" ]

To build this image and override APK_PACKAGE_REGISTRY:

$ docker build --build-arg APK_PACKAGE_REGISTRY=mirror.fit.cvut.cz --no-cache --network host -t my-app-image .

bash - How do I use variables in a sed command? - Ask Ubuntu
How to assign variable and use sed to replace contents of configuration file in Dockerfile? - Unix & Linux Stack Exchange


USER

  • Set the user name or UID to use when running the image in addition to any subsequent CMD, ENTRYPOINT, or RUN instructions that follow it in the Dockerfile.
  • sets the current user
  • this user is ignored by ADD and COPY commands (you need to use --chown)
  • if your service/app can run as non-root, run it as non-root
  • node Docker images from DockerHub contain by default pre-created non-root user node and group node for this purpose

RUN groupadd -g 999 appuser && \
useradd -r -u 999 -g appuser appuser
USER appuser

Towards unprivileged container builds

[Docker RUN vs CMD vs ENTRYPOINT by Yury Pitsishin]
What is the difference between CMD and ENTRYPOINT in a Dockerfile?

The ENTRYPOINT specifies a command that will always be executed when the container starts.
The CMD specifies arguments that will be fed to the ENTRYPOINT.

Dockerfile cheat sheet (kapeli.com)
Dockerfile: ENTRYPOINT vs CMD

Multi-stage build


This is one of the use cases which shows benefits of multi-staged build:
Docker container running golang http.Client getting error `certificate signed by unknown authority`

---
If we already have app binary built and can simply copy it onto an image but still have to add certificates, Dockerfile can look like:

FROM golang:alpine as build
RUN apk --no-cache add ca-certificates

FROM scratch
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY ./bin/my_app /my_app
CMD ["/my_app"]
---
If we set working directory in the image created at first stage, it will remain set to the same path in the following images:

FROM python:3-alpine as base

# Required for installing psycopg2 (see https://github.com/psycopg/psycopg2/issues/684)
RUN apk update && apk add --no-cache postgresql-dev python3-dev gcc musl-dev

ENV appDir /usr/local/src/python-demo
WORKDIR ${appDir}

COPY ./requirements.txt ./
RUN pip install -r requirements.txt

FROM base
COPY . .
COPY src/ ./src
RUN pwd // /usr/local/src/python-demo
CMD [ "python", "./python_demo.py" ]

---

FROM scratch

If we use FROM scratch then we can't use/execute bash/sh terminal if we attach to the container from the outside. The lightest image which provides bash terminal is alpine:

FROM alpine

alpine contains /bin/sh so we can use it via

$ docker exec -it <container_name> sh

Attaching to a docker container with base image scratch?

Why we needed to run apk add ca-certificates?
Install Certificates in Alpine Image to establish Secured Communication (SSL/TLS)

---

.dockerignore


  • added manually in the same directory where Dockerfile resides
  • a newline-separated list of patterns that define a set of files and/or directories that should be ignored by ADD and COPY commands in Dockerfile
  • should contain any directory/file present in the same directory as .dockerfile but which should not be in the newly built image e.g. application's output directory (present on the dev machine and populated during testing) which can be large in size. This can cause sending unnecessary files to Docker daemon and long times for building an image:
$ docker build -t my_image .
...
Sending build context to Docker daemon  20.66GB


.dockerignore Example:

# comment
.git
.gitignore
*/temp*
*/*/temp*
temp
 *.md
!README.md

Can dockerfile be put in .dockerignore?

Linter



Example:

$ docker run --rm -i hadolint/hadolint < Dockerfile
Unable to find image 'hadolint/hadolint:latest' locally
latest: Pulling from hadolint/hadolint
447f1c00f9d8: Pull complete 
Digest: sha256:6e67b08b2f9b3cf57616cfc92adb8864b74b02f079d70eabc944b29f05aff5f9
Status: Downloaded newer image for hadolint/hadolint:latest
/dev/stdin:27 DL3025 Use arguments JSON notation for CMD and ENTRYPOINT arguments


Docker CLI Commands


---
$ docker --help

Usage: docker [OPTIONS] COMMAND

A self-sufficient runtime for containers

Options:
      --config string      Location of client config files (default "/home/bojan/.docker")
  -D, --debug              Enable debug mode
  -H, --host list          Daemon socket(s) to connect to
  -l, --log-level string   Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")
      --tls                Use TLS; implied by --tlsverify
      --tlscacert string   Trust certs signed only by this CA (default "/home/bojan/.docker/ca.pem")
      --tlscert string     Path to TLS certificate file (default "/home/bojan/.docker/cert.pem")
      --tlskey string      Path to TLS key file (default "/home/bojan/.docker/key.pem")
      --tlsverify          Use TLS and verify the remote
  -v, --version            Print version information and quit

Management Commands:
  builder     Manage builds
  config      Manage Docker configs
  container   Manage containers
  engine      Manage the docker engine
  image       Manage images
  network     Manage networks
  node        Manage Swarm nodes
  plugin      Manage plugins
  secret      Manage Docker secrets
  service     Manage services
  stack       Manage Docker stacks
  swarm       Manage Swarm
  system      Manage Docker
  trust       Manage trust on Docker images
  volume      Manage volumes

Commands:
  attach      Attach local standard input, output, and error streams to a running container
  build       Build an image from a Dockerfile
  commit      Create a new image from a container's changes
  cp          Copy files/folders between a container and the local filesystem
  create      Create a new container
  diff        Inspect changes to files or directories on a container's filesystem
  events      Get real time events from the server
  exec        Run a command in a running container
  export      Export a container's filesystem as a tar archive
  history     Show the history of an image
  images      List images
  import      Import the contents from a tarball to create a filesystem image
  info        Display system-wide information
  inspect     Return low-level information on Docker objects
  kill        Kill one or more running containers
  load        Load an image from a tar archive or STDIN
  login       Log in to a Docker registry
  logout      Log out from a Docker registry
  logs        Fetch the logs of a container
  pause       Pause all processes within one or more containers
  port        List port mappings or a specific mapping for the container
  ps          List containers
  pull        Pull an image or a repository from a registry
  push        Push an image or a repository to a registry
  rename      Rename a container
  restart     Restart one or more containers
  rm          Remove one or more containers
  rmi         Remove one or more images
  run         Run a command in a new container
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
  search      Search the Docker Hub for images
  start       Start one or more stopped containers
  stats       Display a live stream of container(s) resource usage statistics
  stop        Stop one or more running containers
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
  top         Display the running processes of a container
  unpause     Unpause all processes within one or more containers
  update      Update configuration of one or more containers
  version     Show the Docker version information
  wait        Block until one or more containers stop, then print their exit codes

Run 'docker COMMAND --help' for more information on a command.
---


Builds an image from a Dockerfile.

$ docker build --help
Usage: docker build [OPTIONS] PATH | URL | -
Build an image from a Dockerfile

Options:
--add-host list Add a custom host-to-IP mapping (host:ip)
--build-arg list Set build-time variables
--cache-from strings Images to consider as cache sources
--cgroup-parent string Optional parent cgroup for the container
--compress Compress the build context using gzip
--cpu-period int Limit the CPU CFS (Completely Fair Scheduler) period
--cpu-quota int Limit the CPU CFS (Completely Fair Scheduler) quota
-c, --cpu-shares int CPU shares (relative weight)
--cpuset-cpus string CPUs in which to allow execution (0-3, 0,1)
--cpuset-mems string MEMs in which to allow execution (0-3, 0,1)
--disable-content-trust Skip image verification (default true)
-f, --file string Name of the Dockerfile (Default is 'PATH/Dockerfile')
--force-rm Always remove intermediate containers
--iidfile string Write the image ID to the file
--isolation string Container isolation technology
--label list Set metadata for an image
-m, --memory bytes Memory limit
--memory-swap bytes Swap limit equal to memory plus swap: '-1' to enable unlimited swap
--network string Set the networking mode for the RUN instructions during build (default "default")
--no-cache Do not use cache when building the image
--pull Always attempt to pull a newer version of the image
-q, --quiet Suppress the build output and print image ID on success
--rm Remove intermediate containers after a successful build (default true)
--security-opt strings Security options
--shm-size bytes Size of /dev/shm
-t, --tag list Name and optionally a tag in the 'name:tag' format
--target string Set the target build stage to build.
--ulimit ulimit Ulimit options (default [])



The PATH specifies where to find the files for the “context” of the build on the Docker daemon.

Example (has to be run in a directory which contains Dockerfile):

$ docker build -t <my username>/<my-app-name> .

Example of how to build and run a Docker image:

$ docker build -t jsonschema2db . && docker run jsonschema2db


If Docker has to fetch some resources from remote host whose domain name can't be resolved from within Docker native network but can from your local/dev host network use --network host:

$ docker build --network host -t my-image . 

---


docker container

$ docker container 

Usage:  docker container COMMAND

Manage containers

Commands:
  attach      Attach local standard input, output, and error streams to a running container
  commit      Create a new image from a container's changes
  cp          Copy files/folders between a container and the local filesystem
  create      Create a new container
  diff        Inspect changes to files or directories on a container's filesystem
  exec        Run a command in a running container
  export      Export a container's filesystem as a tar archive
  inspect     Display detailed information on one or more containers
  kill        Kill one or more running containers
  logs        Fetch the logs of a container
  ls          List containers
  pause       Pause all processes within one or more containers
  port        List port mappings or a specific mapping for the container
  prune       Remove all stopped containers
  rename      Rename a container
  restart     Restart one or more containers
  rm          Remove one or more containers
  run         Run a command in a new container
  start       Start one or more stopped containers
  stats       Display a live stream of container(s) resource usage statistics
  stop        Stop one or more running containers
  top         Display the running processes of a container
  unpause     Unpause all processes within one or more containers
  update      Update configuration of one or more containers
  wait        Block until one or more containers stop, then print their exit codes

Run 'docker container COMMAND --help' for more information on a command.

---

If we try to start some container which requires opening some port on the localhost while another running container has already opened it, we might get the following error:

$ docker-compose up --build

Starting my_app_1 ... 

ERROR: for my-app_db_1  Cannot start service db: driver failed programming external connectivity on endpoint my-app_db_1 (a456b10867b734493c831aa99f227147110f61233652c4984415c12ecdf9a9b3): Bind for 0.0.0.0:5432 failed: port is Starting my-app_my-service_1 ... done

ERROR: for db  Cannot start service db: driver failed programming external connectivity on endpoint my-app_db_1 (a456b10867b734493c831aa99f227147110f61233652c4984415c12ecdf9a9b3): Bind for 0.0.0.0:5432 failed: port is already allocated
ERROR: Encountered errors while bringing up the project.

To resolve this, we first need to check which containers are running and then to stop them:

$ docker container ls 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
499c43a9c28b        postgres:latest     "docker-entrypoint.s…"   3 days ago          Up 3 days           0.0.0.0:5432->5432/tcp   my-app-2_db_1

$ docker container stop my-app-2_db_1
my-app-2_db_1

Let's verify that no containers are running:

$ docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

---

docker container ls 


$ docker container ls --help

Usage:  docker container ls [OPTIONS]

List containers

Aliases:
  ls, ps, list

Options:
  -a, --all             Show all containers (default shows just running)
  -f, --filter filter   Filter output based on conditions provided
      --format string   Pretty-print containers using a Go template
  -n, --last int        Show n last created containers (includes all states) (default -1)
  -l, --latest          Show the latest created container (includes all states)
      --no-trunc        Don't truncate output
  -q, --quiet           Only display numeric IDs
  -s, --size            Display total file sizes



To list all containers:

$ docker container ls -a

To list only numeric IDs of all containers:

$ docker container ls -a -q

or

$ docker container ls -aq

---

docker container rm


$ docker container rm --help

Usage:  docker container rm [OPTIONS] CONTAINER [CONTAINER...]

Remove one or more containers

Options:
  -f, --force     Force the removal of a running container (uses SIGKILL)
  -l, --link      Remove the specified link
  -v, --volumes   Remove the volumes associated with the container


To remove all containers:

$ docker container rm $(docker container ls -aq)


To display detailed information on one or more containers:

$ docker container inspect <container id or name>


---

docker create


---
$ docker create --help

Usage: docker create [OPTIONS] IMAGE [COMMAND] [ARG...]

Create a new container

Options:
      --add-host list                  Add a custom host-to-IP mapping (host:ip)
  -a, --attach list                    Attach to STDIN, STDOUT or STDERR
      --blkio-weight uint16            Block IO (relative weight), between 10 and 1000, or 0 to disable (default 0)
      --blkio-weight-device list       Block IO weight (relative device weight) (default [])
      --cap-add list                   Add Linux capabilities
      --cap-drop list                  Drop Linux capabilities
      --cgroup-parent string           Optional parent cgroup for the container
      --cidfile string                 Write the container ID to the file
      --cpu-period int                 Limit CPU CFS (Completely Fair Scheduler) period
      --cpu-quota int                  Limit CPU CFS (Completely Fair Scheduler) quota
      --cpu-rt-period int              Limit CPU real-time period in microseconds
      --cpu-rt-runtime int             Limit CPU real-time runtime in microseconds
  -c, --cpu-shares int                 CPU shares (relative weight)
      --cpus decimal                   Number of CPUs
      --cpuset-cpus string             CPUs in which to allow execution (0-3, 0,1)
      --cpuset-mems string             MEMs in which to allow execution (0-3, 0,1)
      --device list                    Add a host device to the container
      --device-cgroup-rule list        Add a rule to the cgroup allowed devices list
      --device-read-bps list           Limit read rate (bytes per second) from a device (default [])
      --device-read-iops list          Limit read rate (IO per second) from a device (default [])
      --device-write-bps list          Limit write rate (bytes per second) to a device (default [])
      --device-write-iops list         Limit write rate (IO per second) to a device (default [])
      --disable-content-trust          Skip image verification (default true)
      --dns list                       Set custom DNS servers
      --dns-option list                Set DNS options
      --dns-search list                Set custom DNS search domains
      --entrypoint string              Overwrite the default ENTRYPOINT of the image
  -e, --env list                       Set environment variables
      --env-file list                  Read in a file of environment variables
      --expose list                    Expose a port or a range of ports
      --group-add list                 Add additional groups to join
      --health-cmd string              Command to run to check health
      --health-interval duration       Time between running the check (ms|s|m|h) (default 0s)
      --health-retries int             Consecutive failures needed to report unhealthy
      --health-start-period duration   Start period for the container to initialize before starting health-retries countdown (ms|s|m|h) (default 0s)
      --health-timeout duration        Maximum time to allow one check to run (ms|s|m|h) (default 0s)
      --help                           Print usage

-h, --hostname string                
Container host name

      --init                           Run an init inside the container that forwards signals and reaps processes
  -i, --interactive                    Keep STDIN open even if not attached
      --ip string                      IPv4 address (e.g., 172.30.100.104)
      --ip6 string                     IPv6 address (e.g., 2001:db8::33)
      --ipc string                     IPC mode to use
      --isolation string               Container isolation technology
      --kernel-memory bytes            Kernel memory limit
  -l, --label list                     Set meta data on a container
      --label-file list                Read in a line delimited file of labels
      --link list                      Add link to another container
      --link-local-ip list             Container IPv4/IPv6 link-local addresses
      --log-driver string              Logging driver for the container
      --log-opt list                   Log driver options
      --mac-address string             Container MAC address (e.g., 92:d0:c6:0a:29:33)
  -m, --memory bytes                   Memory limit
      --memory-reservation bytes       Memory soft limit
      --memory-swap bytes              Swap limit equal to memory plus swap: '-1' to enable unlimited swap
      --memory-swappiness int          Tune container memory swappiness (0 to 100) (default -1)
      --mount mount                    Attach a filesystem mount to the container
      --name string                    Assign a name to the container
      --network string                 Connect a container to a network (default "default")
      --network-alias list             Add network-scoped alias for the container
      --no-healthcheck                 Disable any container-specified HEALTHCHECK
      --oom-kill-disable               Disable OOM Killer
      --oom-score-adj int              Tune host's OOM preferences (-1000 to 1000)
      --pid string                     PID namespace to use
      --pids-limit int                 Tune container pids limit (set -1 for unlimited)
      --privileged                     Give extended privileges to this container
  -p, --publish list                   Publish a container's port(s) to the host
  -P, --publish-all                    Publish all exposed ports to random ports
      --read-only                      Mount the container's root filesystem as read only
      --restart string                 Restart policy to apply when a container exits (default "no")
      --rm                             Automatically remove the container when it exits
      --runtime string                 Runtime to use for this container
      --security-opt list              Security Options
      --shm-size bytes                 Size of /dev/shm
      --stop-signal string             Signal to stop a container (default "SIGTERM")
      --stop-timeout int               Timeout (in seconds) to stop a container
      --storage-opt list               Storage driver options for the container
      --sysctl map                     Sysctl options (default map[])
      --tmpfs list                     Mount a tmpfs directory
  -t, --tty                            Allocate a pseudo-TTY
      --ulimit ulimit                  Ulimit options (default [])
  -u, --user string                    Username or UID (format: <name|uid>[:<group|gid>])
      --userns string                  User namespace to use
      --uts string                     UTS namespace to use
  -v, --volume list                    Bind mount a volume
      --volume-driver string           Optional volume driver for the container
      --volumes-from list              Mount volumes from the specified container(s)
  -w, --workdir string                 Working directory inside the container
---

Examples:

$ docker create \
-e DB_HOST=121.1.0.1 \
-e DB_PORT=5432 \
-e DB_NAME=test_db \
-e DB_USER=postgres \
-e DB_PASSWORD=postgres \
-e OUTPUT_DIR=./data-vol \
--rm \
-it \
--mount type=bind,src="$(pwd)/data-vol",target=/data-vol \
--network=bridge \
--name my_app_test_container \
docker.example.com/bojan/myapp:build-28 


docker exec


To execute a command inside a running container, use docker exec. For example, we can run a bash terminal as:

$ docker exec -it my-postgres bash
root@a4a7486fea59:/# 

-i // keeps stdin opened
-t // allocates pseudo TTY

In this terminal we can run usual Linux commands as we were inside the container:

root@a4a7486fea59:/# ls
bin  boot  dev docker-entrypoint-initdb.d  docker-entrypoint.sh  etc  home  lib  lib64  media mnt  opt  proc root  run  sbin  srv  sys  tmp usr  var
root@a4a7486fea59:/# pwd
/

not able to use docker exec shell 
Try the alpine tag of image:

$ docker run --name gorush -d appleboy/gorush:alpine
$ docker exec -ti gorush /bin/sh

docker image


To list all images:

$ docker image ls

To remove some image:

$ docker image rm image_id


docker inspect



$ docker inspect --help

Usage: docker inspect [OPTIONS] NAME|ID [NAME|ID...]

Return low-level information on Docker objects

Options:
  -f, --format string   Format the output using the given Go template
  -s, --size            Display total file sizes if the type is container
      --type string     Return JSON for specified type


Examples:

How to find mounting points of a (stopped) container? E.g. find local directory that is mounted as a volume on some container.

$ docker inspect -f {{.Mounts}} my_container
[{bind  /home/bojan/tmp/data-vol /data-vol   true rprivate}]

What to Inspect When You're Inspecting

docker logs

$ docker logs --help

Usage: docker logs [OPTIONS] CONTAINER

Fetch the logs of a container

Options:
      --details        Show extra details provided to logs
  -f, --follow         Follow log output
      --since string   Show logs since timestamp (e.g. 2013-01-02T13:23:37) or relative (e.g. 42m for 42 minutes)
      --tail string    Number of lines to show from the end of the logs (default "all")
  -t, --timestamps     Show timestamps
      --until string   Show logs before a timestamp (e.g. 2013-01-02T13:23:37) or relative (e.g. 42m for 42 minutes)

Example:

$ docker logs my_app >& my_app.log

---

docker network



$ docker network --help

Usage: docker network COMMAND

Manage networks

Commands:
  connect     Connect a container to a network
  create      Create a network
  disconnect  Disconnect a container from a network
  inspect     Display detailed information on one or more networks
  ls          List networks
  prune       Remove all unused networks
  rm          Remove one or more networks

Run 'docker network COMMAND --help' for more information on a command.


List all networks:


$ docker network ls
NETWORK ID          NAME                             DRIVER              SCOPE
110d23a9b23f        bridge                           bridge              local
b32aba0ecc85        my_app1       bridge              local
5a91d6b95b25        my_app2   bridge              local
7422e6165f7a        my_app3                     bridge              local
b2977102daa4        my_app4_test-network                bridge              local
e829cad5a344        host                             host                local
6b0d605ed4a5        none                             null                local


Connect a container to the network (of some other container):


$ docker network connect --help

Usage: docker network connect [OPTIONS] NETWORK CONTAINER

Connect a container to a network

Options:
      --alias strings           Add network-scoped alias for the container
      --ip string               IPv4 address (e.g., 172.30.100.104)
      --ip6 string              IPv6 address (e.g., 2001:db8::33)
      --link list               Add link to another container
      --link-local-ip strings   Add a link-local address for the container


Use case example:

Running Postgres DB in one container (based on postgres image; container runs in its own network) and connecting to it via pgAdmin which runs in another container (based on dpage/pgadmin4 image).

docker container ls shows that my_app_db_1 is up and running with port mapping as 0.0.0.0:5432->5432/tcp. This container runs Postgres DB.

To find the name of the network this container is connected to use docker inspect <container_name> and in the output json look for "NetworkSettings" > "Networks". There should be a network name like "my_app_default".

Let's inspect that network:

$ docker network inspect my_app_default
[
    {
        "Name": "my_app_default",
        "Id": "5a91d6b95b25fdd6d24e921e1ccdb69f24ae4b1c509188ccfc087acd330375ca",
        "Created": "2019-06-05T10:19:11.576495786+01:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.19.0.0/16",
                    "Gateway": "172.19.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": true,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "9ae5dfe822348906d2bdf2b55314a323f7ba03360eb2edf8e5d7d42afca40e34": {
                "Name": "my_app_service",
                "EndpointID": "a5230696caabc7d230df8f589066b8028c3b03493a2f05ed0dc5e224944952fc",
                "MacAddress": "02:42:ac:13:00:03",
                "IPv4Address": "172.19.0.3/16",
                "IPv6Address": ""
            },
            "e52e5d6de6b6a062d2cbfaf921f3365f20db0208511a906cab6143528a14ee6d": {
                "Name": "my_app_db_1",
                "EndpointID": "bbe87692635abe7cd45a3980d0982ca1dbc6c9a5718a267935659cfb036b2da1",
                "MacAddress": "02:42:ac:13:00:02",
                "IPv4Address": "172.19.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {
            "com.docker.compose.network": "default",
            "com.docker.compose.project": "my_app",
            "com.docker.compose.version": "1.23.2"
        }
    }
]

my_app_db_1 is the name of the container which is running db service (Postgres) as I specified in docker-compose.yml.

Now, I want to run pgAdmin DB client (which is also a web server...) from its own container, based on dpage/pgadmin4 image:

$ docker run -p 5051:5051 -d -e "PGADMIN_DEFAULT_EMAIL=bojan.komazec@example.com" -e "PGADMIN_DEFAULT_PASSWORD=postgres" -e "PGADMIN_LISTEN_PORT=5051" --name pgadmin dpage/pgadmin4
baf9343368f9cb20a0dd9ab1a4763eaf08df03f2ee667f979b4e3466bc20d7b1

We can use docker container ls to verify that this container is now up and running, with port mappings as 80/tcp, 443/tcp, 0.0.0.0:5051->5051/tcp. We can now open in browser on the local host the address http://localhost:5051/ which should open pgAdmin login page. If we try to add DB server with IP address 172.19.0.2 (as listed in the postgres container network spec above), connecting to it will fail as pgAdmin runs in its own network. We need to connect pgadmin container to my_app_default network:

$ docker network connect my_app_default pgadmin

We can now use 172.19.0.2 address to connect to DB from pgAdmin web app.

If we again inspect my_app_default network we can verify that there is one more container attached to it: pgadmin.

To avoid issuing two commands, we can specify network container shall connect to in docker run command:

$ docker run -p 5051:5051 -d -e "PGADMIN_DEFAULT_EMAIL=bojan.komazec@example.com" -e "PGADMIN_DEFAULT_PASSWORD=postgres" -e "PGADMIN_LISTEN_PORT=5051" --network=my_app_default --name pgadmin dpage/pgadmin4


Creating a network:


$ docker network create --help

Usage: docker network create [OPTIONS] NETWORK

Create a network

Options:
      --attachable           Enable manual container attachment
      --aux-address map      Auxiliary IPv4 or IPv6 addresses used by Network driver (default map[])
      --config-from string   The network from which copying the configuration
      --config-only          Create a configuration only network
  -d, --driver string        Driver to manage the Network (default "bridge")
      --gateway strings      IPv4 or IPv6 Gateway for the master subnet
      --ingress              Create swarm routing-mesh network
      --internal             Restrict external access to the network
      --ip-range strings     Allocate container ip from a sub-range
      --ipam-driver string   IP Address Management Driver (default "default")
      --ipam-opt map         Set IPAM driver specific options (default map[])
      --ipv6                 Enable IPv6 networking
      --label list           Set metadata on a network
  -o, --opt map              Set driver specific options (default map[])
      --scope string         Control the network's scope
      --subnet strings       Subnet in CIDR format that represents a network segment

Example:

Create a network:

$ docker network create --subnet=172.18.0.0/24 --gateway=172.18.0.1  mynet123

Attach container to that network and assign a static IP address to it:

$ docker run --net mynet123 --ip 172.18.0.22 -it ubuntu bash


Destroying a network

$ docker network rm mynet123

---

docker ps


To list all running containers use docker ps:

$ docker ps
CONTAINER ID  IMAGE   COMMAND         CREATED     STATUS      PORTS                      NAMES
b9f263f2b517 postgres "some.command…" 9 hours ago Up 5 hours  0.0.0.0:5432->5432/tcp  my_project_postgres_1

If no containers are running:

$ sudo docker ps
CONTAINER ID    IMAGE           COMMAND         CREATED         STATUS          PORTS               NAMES


To list all containers, use docker ps -a.


docker pull


docker pull pulls an image from the repository.

Use:

$ docker pull <image_name>:<tag_name>

If no tag is provided, Docker Engine uses the :latest tag as a default.

Apart from pulling some image for the first time, this command is used to pull a new version of the existing image. [Update a docker container to the latest version]

In my case, I have been running pgAdmin4 from within a container but after some time I started getting a popup on pgAdmin4 main web page that I am using the old version of it. My course of actions was:

$ docker images | grep pgadmin
dpage/pgadmin4                  latest               c32b95c07a00        5 weeks ago         237MB

$ docker pull dpage/pgadmin4
Using default tag: latest
latest: Pulling from dpage/pgadmin4
e7c96db7181b: Already exists 
...
44bc3cf004be: Already exists 
aa774cf9fd8b: Pull complete 
...
660e231737f7: Pull complete 
Digest: sha256:2c46b3e631f33434246a2a51134e3a43951b00c5639f7fc158b4b973879f9ea3
Status: Downloaded newer image for dpage/pgadmin4:latest

---
How to upgrade docker container after its image changed
---

docker run


docker run = docker create + docker start

A container is an instance of an image and pull only downloads the image, it doesn't create a container.

docker run creates a container from the image you choose.

If you run

$ docker run myImage

...N times, docker ps -a will show N containers based on that image.

Why “Docker run” creates new container every time?

Containers do not modify images. Any changes made to a container you've started via docker run won't affect another container run from the same image

Container process that runs is isolated in that it has its own:
  • file system
  • networking
  • isolated process tree separate from the host

$ docker run --help

Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]


Run a command in a new container


Options:

      --add-host list                  Add a custom host-to-IP mapping (host:ip)
  -a, --attach list                    Attach to STDIN, STDOUT or STDERR
      --blkio-weight uint16            Block IO (relative weight), between 10 and 1000, or 0 to disable (default 0)
      --blkio-weight-device list       Block IO weight (relative device weight) (default [])
      --cap-add list                   Add Linux capabilities
      --cap-drop list                  Drop Linux capabilities
      --cgroup-parent string           Optional parent cgroup for the container
      --cidfile string                 Write the container ID to the file
      --cpu-count int                  CPU count (Windows only)
      --cpu-percent int                CPU percent (Windows only)
      --cpu-period int                 Limit CPU CFS (Completely Fair Scheduler) period
      --cpu-quota int                  Limit CPU CFS (Completely Fair Scheduler) quota
      --cpu-rt-period int              Limit CPU real-time period in microseconds
      --cpu-rt-runtime int             Limit CPU real-time runtime in microseconds
  -c, --cpu-shares int                 CPU shares (relative weight)
      --cpus decimal                   Number of CPUs
      --cpuset-cpus string             CPUs in which to allow execution (0-3, 0,1)
      --cpuset-mems string             MEMs in which to allow execution (0-3, 0,1)
  
      -d, --detach                     Run container in background and print container ID

      --detach-keys string             Override the key sequence for detaching a container

      --device list                    Add a host device to the container
      --device-cgroup-rule list        Add a rule to the cgroup allowed devices list
      --device-read-bps list           Limit read rate (bytes per second) from a device (default [])
      --device-read-iops list          Limit read rate (IO per second) from a device (default [])
      --device-write-bps list          Limit write rate (bytes per second) to a device (default [])
      --device-write-iops list         Limit write rate (IO per second) to a device (default [])
      --disable-content-trust          Skip image verification (default true)
      --dns list                       Set custom DNS servers
      --dns-option list                Set DNS options
      --dns-search list                Set custom DNS search domains
      --entrypoint string              Overwrite the default ENTRYPOINT of the image

      -e, --env list                   Set environment variables


      --env-file list                  Read in a file of environment variables

      --expose list                    Expose a port or a range of ports
      --group-add list                 Add additional groups to join
      --health-cmd string              Command to run to check health
      --health-interval duration       Time between running the check (ms|s|m|h) (default 0s)
      --health-retries int             Consecutive failures needed to report unhealthy
      --health-start-period duration   Start period for the container to initialize before starting health-retries countdown (ms|s|m|h) (default 0s)
      --health-timeout duration        Maximum time to allow one check to run (ms|s|m|h) (default 0s)
      --help                           Print usage
      -h, --hostname string            Container host name
      --init                           Run an init inside the container that forwards signals and reaps processes

      -i, --interactive               
Keep STDIN open even if not attached

      --io-maxbandwidth bytes          Maximum IO bandwidth limit for the system drive (Windows only)

      --io-maxiops uint                Maximum IOps limit for the system drive (Windows only)
      --ip string                      IPv4 address (e.g., 172.30.100.104)
      --ip6 string                     IPv6 address (e.g., 2001:db8::33)
      --ipc string                     IPC mode to use
      --isolation string               Container isolation technology
      --kernel-memory bytes            Kernel memory limit
  -l, --label list                     Set meta data on a container
      --label-file list                Read in a line delimited file of labels
      --link list                      Add link to another container
      --link-local-ip list             Container IPv4/IPv6 link-local addresses
      --log-driver string              Logging driver for the container
      --log-opt list                   Log driver options
      --mac-address string             Container MAC address (e.g., 92:d0:c6:0a:29:33)
  -m, --memory bytes                   Memory limit
      --memory-reservation bytes       Memory soft limit
      --memory-swap bytes              Swap limit equal to memory plus swap: '-1' to enable unlimited swap
      --memory-swappiness int          Tune container memory swappiness (0 to 100) (default -1)
      
      --mount mount                    Attach a filesystem mount to the container

      --name string                    Assign a name to the container

      
      --network string                 Connect a container to a network (default "default")

      --network-alias list             Add network-scoped alias for the container

      --no-healthcheck                 Disable any container-specified HEALTHCHECK
      --oom-kill-disable               Disable OOM Killer
      --oom-score-adj int              Tune host's OOM preferences (-1000 to 1000)
      --pid string                     PID namespace to use
      --pids-limit int                 Tune container pids limit (set -1 for unlimited)
      --platform string                Set platform if server is multi-platform capable
      --privileged                     Give extended privileges to this container

      -p, --publish list               Publish a container's port(s) to the host


  -P, --publish-all                    Publish all exposed ports to random ports

      --read-only                      Mount the container's root filesystem as read only
      --restart string                 Restart policy to apply when a container exits (default "no")

      --rm                             
Automatically remove the container when it exits; this means it will not be listed in "docker ps -a" output after it terminates.

      --runtime string                 Runtime to use for this container

      --security-opt list              Security Options
      --shm-size bytes                 Size of /dev/shm
      --sig-proxy                      Proxy received signals to the process (default true)
      --stop-signal string             Signal to stop a container (default "SIGTERM")
      --stop-timeout int               Timeout (in seconds) to stop a container
      --storage-opt list               Storage driver options for the container
      --sysctl map                     Sysctl options (default map[])
      --tmpfs list                     Mount a tmpfs directory

      -t, --tty                        
Allocate a pseudo-TTY
(If you wander WTF is TTY read this)

      --ulimit ulimit                  Ulimit options (default [])


      -u, --user string               
Username or UID (format: <name|uid>[:<group|gid>])

      --userns string                  User namespace to use

      --uts string                     UTS namespace to use

      -v, --volume list                
Bind mount a volume

      --volume-driver string           Optional volume driver for the container

      --volumes-from list              Mount volumes from the specified container(s)
  -w, --workdir string                 Working directory inside the container


For interactive processes (like a shell), you must use -i -t together in order to allocate a tty for the container process. -i -t is often written -it. [source]

Confused about Docker -t option to Allocate a pseudo-TTY

Example: 

This example shows how it's easy to fetch, spin and use a specific version of Golang (v1.11) with Docker:

$ docker run --rm -it golang:1.11
Unable to find image 'golang:1.11' locally
1.11: Pulling from library/golang
e79bb959ec00: Already exists 
d4b7902036fe: Already exists 
1b2a72d4e030: Already exists 
d54db43011fd: Already exists 
963c818ebafc: Already exists 
66831bab8cde: Pull complete 
0ac2e04178ce: Pull complete 
Digest: sha256:c096aaab963e25f78d226e841ad258ab3cba8c6a4c345c24166a5755686734f1
Status: Downloaded newer image for golang:1.11
root@bee14b1ffe61:/go# go version
go version go1.11.6 linux/amd64
root@bee14b1ffe61:/go# exit
exit

Example:

docker run -p 443:443 \
        -v "/private/var/lib/pgadmin:/var/lib/pgadmin" \
        -v "/path/to/certificate.cert:/certs/server.cert" \
        -v "/path/to/certificate.key:/certs/server.key" \
        -v "/tmp/servers.json:/servers.json" \
        -e "PGADMIN_DEFAULT_EMAIL=user@domain.com" \
        -e "PGADMIN_DEFAULT_PASSWORD=SuperSecret" \
        -e "PGADMIN_ENABLE_TLS=True" \
        -d dpage/pgadmin4


Pulling the image from Docker Hub


docker run checks if image exists locally and if not it performs docker pull and downloads it from Docker Hub. [1]

Container identification


Container can be identified by:

  • UUID
    • assigned by the daemon
    • can be:
      • long
      • short
  • name
    • set by the developer via --name argument

Container Modes (-d) 


Docker can run processes (containers) in one of these two modes:

  • foreground
    • default mode
    • console is attached to process' stdin, stdout, stderr
  • background (detached)
    • -d has to be passed to docker run
    • container exits when 
      • the root process used to run container exits OR
      • when daemon exits (if this happens first)

Exposing Ports


If some process in the container is listening on some port and we want to allow connections from outside the container, we can open (expose) these incoming ports via -p option which publishes single port or range of ports to the host. Port number that service listens inside the container does not need to be the same as the port exposed to the host (where external clients connect). These mappings are specified like in these examples:

-p <host_port(s)>:<container_port(s)>/protocol

-p 1234:1234 // single port, all protocols
-p 1234:1234/tcp // allow only TCP protocol
-p 1234-1240:1234-1240 // range
-p 1234-1240:1234-1240/tcp // range, TCP protocol only
-p 127.0.0.1:80:8080/tcp // tcp port 8080 is mapped onto host's port 80

Networking

Use case:

  • DB is running in one container and DB client is running in another container
  • DB client is using host name (not IP address) of the first container
Setup:

  • Both containers have to be on the same network. This can be achieved in two ways:
    • DB container does not specify any network but DB client container is using --network=container:<DB_container_name>
    • a custom network is created and both containers are using --network=<network_name>
  • DB has to have set network alias so DB client can use it as DB's host name
Creating custom network:

$ docker network create \
--subnet=172.18.0.0/24 \
--gateway 172.18.0.1 \
custom_network

Starting DB container:

$ docker run \
--name postgres \
--network custom_network \
--publish 5432:5432 \
--hostname db \ <-- this is irrelevant for DNS resolution
--network-alias db \ <-- this is relevant for DNS resolution
--ip 172.18.0.2 \
...
postgres

Starting DB client container:

$ docker run \
-e PGHOST=db \
--name db_client \
--network custom_network \
...
dockerhub.com/mydbclient

From the docs: --hostname option specifies the hostname a container uses for itself. Defaults to the container’s ID if not specified.

To check container's network do:

$ docker inspect <container_name_or_id>

or

$ docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $INSTANCE_ID

Container's IPv4 address has to be found in NetworkSettings.Networks.<network_name>.IPAddress. For backward compatibility and only for the default bridge network, the IPv4 address will also be listed in NetworkSettings.IPAddress.


Can't resolve set hostname from another docker container in same network

If (Node.js) app for some reason can't resolve hostname, its networking stack might error with:
Error: getaddrinfo EAI_AGAIN

Error: getaddrinfo EAI_AGAIN
My Docker container does not have IP address. Why?
docker inspect <container-id> returns blank IP address
Troubleshooting Container Networking


Useful for testing: blocking particular domain for Docker container

Use --add-host. Example:

$ docker run -e APP_ENV=dev -e DB_HOST=1.2.3.4 -e DB_PORT=5432 -e DB_NAME=my_db_dev -e DB_USER=postgres -e DB_PASSWORD=postgres -e OUTPUT_DIR=./data-vol --rm -it --mount type=bind,src="$(pwd)/data-vol",target=/data-vol --network=db_default --add-host dev.example.com:0.0.0.0 --name my-app-container my-app-image --param0=arg0

Adding something like

RUN echo "0.0.0.0 dev.example.com" >> /etc/hosts && cat /etc/hosts

to Dockerfile won't work.


How to make Docker using Proxy server?

One of the options is to use environment variables:

docker run \
...
-e HTTP_PROXY=10.21.32.40:8080 \
-e HTTPS_PROXY=10.21.32.40:8080 \
...

Configure Docker to use a proxy server | Docker Documentation

Running Docker Containers as Specified User


Processes In Containers Should Not Run As Root
Running a Docker container as a non-root user
How to use Docker without sudo on Ubuntu

Add current user to docker group (which members can talk to docker service which is running as root):

$ sudo gpasswd -a $USER docker
# or sudo usermod -aG docker $USER
$ newgrp docker

Running Docker Containers as Current Host User
What's the default user for docker exec?
Permission denied on accessing host directory in docker



Environment variables


Use -e option followed by NAME=VALUE like in this example:

-e POSTGRES_PASSWORD=mysecretpassword


Using volumes

Use volumes

From Volume mapping making directories out of files:
When using the -v <host-path>:<container-path> option is used for a bind-mount, docker will look for <host-path> on the host where the daemon runs; if that path does not exist, it will create a directory on that location (as it doesn't know if you wanted to mount a file or a directory; a directory is the default). (Windows-specific: If you don't have a shared drive set-up, docker won't be able to access that path from your host, thus won't find the path inside the VM (thus creates a directory)).
To prevent docker from creating the path if it cannot find it (and produce an error instead), use the --mount option instead of -v. The --mount flag uses a different syntax, which can be found on this page; https://docs.docker.com/engine/admin/volumes/bind-mounts/#start-a-container-with-a-bind-mount


Volumes are the preferred mechanism for persisting data generated by and used by Docker containers.

New users should try --mount syntax which is simpler than --volume syntax.

--mount 'type=volume,src=<VOLUME-NAME>,dst=<CONTAINER-PATH>,volume-driver=local,volume-opt=type=nfs...'


type - type of the mount, which can be bind, volume, or tmpfs
src - For named volumes, this is the name of the volume. May be specified as source or src. It can be either absolute or relative path.
dst - destination takes as its value the path where the file or directory is mounted in the container; May be specified as destination, dst, or target. It has to be absolute path otherwise an error similar to this is issued:

$ docker run --rm -it --mount type=volume,src=./data-vol-src,target=./data-vol-target --name go-demo go-demo
docker: Error response from daemon: invalid mount config for type "volume": invalid mount path: './data-vol-target' mount path must be absolute.
See 'docker run --help'.


Example:

$ docker run  --mount type=volume,source=myvol,target=/app ...


Docker Tip #33: Should You Use the Volume or Mount Flag?

BK: I could not make docker run --mount working when having both type=volume and source=`pwd`/myvol (or $(pwd)/myvol, ${pwd}/myvol, "$(pwd)/myvol", "$(pwd)"/myvol...etc...).

Example:

$ docker run --rm -it --mount type=volume,src="$(pwd)/data-vol",target=/go/src/github.com/BojanKomazec/go-demo/data-vol --name go-demo go-demo
docker: Error response from daemon: create /home/bojan/dev/go/src/github.com/BojanKomazec/go-demo/data-vol: "/home/bojan/dev/go/src/github.com/BojanKomazec/go-demo/data-vol" includes invalid characters for a local volume name, only "[a-zA-Z0-9][a-zA-Z0-9_.-]" are allowed. If you intended to pass a host directory, use absolute path.
See 'docker run --help'.

This is very likely a consequence of Docker's way of handling volumes: When -v (or -- mount type=volume) is specified Docker will create a new volume in the docker host's /var/lib/docker/volumes/new_volume_name/_data and mount to the container. We can't use an arbitrary absolute path for the volume (the one that includes $(pwd)) if volume has to be in a directory predefined by Docker.

Nevertheless, if we switch to binding local host's arbitrary directory to some container's one then $(pwd) works well.

Example:

$ docker run --rm -it --mount type=bind,src="$(pwd)/data-vol",target=/go/src/github.com/BojanKomazec/go-demo/data-vol --name go-demo go-demo

Our application can pick up target directory via environment variable: we need to add e.g. OUTPUT_DIR=./data-vol to .env file or to docker run -e argument.

If some file is created and saved to disk by the application which runs within Docker container, that file will actually be saved on the host's disk, in the directory in container's volume. E.g.

/var/lib/docker/volumes/f84dd5236429fc84c31104335394bd08f5292316c93fb04552e68349877ba0ca/_data/storage/test_example.com/demo_table_from_db.csv

To access (e.g. view) this file, attach to container's terminal as:

$ docker exec -it container_name /bin/bash

or

$ docker exec -it container_name /bin/sh

...if bash is not available in the image.

Example:

$ docker exec -it pgadmin /bin/bash
OCI runtime exec failed: exec failed: container_linux.go:345: starting container process caused "exec: \"/bin/bash\": stat /bin/bash: no such file or directory": unknown
$ docker exec -it pgadmin /bin/sh
/pgadmin4 # ls -la
...

Troubleshooting #1


If you use docker run and then see that container is not running (e.g. the output of docker container ls shows its status as Exited(1)) check the log of the container:

$ docker inspect <container_name>

In the output json look for LogPath attribute:

"LogPath":"/var/lib/docker/containers/62fdb19e88ded813969915891f6a2dec6a83cb3a28c1054fbdd1e001f033ccf6/62fdb19e88ded813969915891f6a2dec6a83cb3a28c1054fbdd1e001f033ccf6-json.log"

Then see the content of the log file:

$ sudo cat /var/lib/docker/containers/62fdb19e88ded813969915891f6a2dec6a83cb3a28c1054fbdd1e001f033ccf6/62fdb19e88ded813969915891f6a2dec6a83cb3a28c1054fbdd1e001f033ccf6-json.log

{"log":"You need to specify PGADMIN_DEFAULT_EMAIL and PGADMIN_DEFAULT_PASSWORD environment variables\n","stream":"stdout","time":"2019-06-05T10:14:22.078604896Z"}

Troubleshooting #2


If Dockerfile specifies an executable to be run via CMD but some of the dependencies of that executable are missing (e.g. base image is alpine so doesn't have some libs installed...) running this container might report an error:

$ docker run  --rm -it --mount type=bind,src="$(pwd)/data-vol",target=/data-vol  --name myapp docker.example.com/myapps/myapp:build-28
standard_init_linux.go:211: exec user process caused "no such file or directory"

To verify that it is indeed binary stated in CMD that is making problems, we can override CMD by specifying /bin/sh as the executable so we can browse the file system of the container:

$ docker run  --rm -it --mount type=bind,src="$(pwd)/data-vol",target=/data-vol  --name myapp docker.example.com/myapps/myapp:build-28 /bin/sh
/ # ls -la
total 8404
drwxr-xr-x    1 root     root          4096 Jul 25 13:27 .
drwxr-xr-x    1 root     root          4096 Jul 25 13:27 ..
-rwxr-xr-x    1 root     root             0 Jul 25 13:27 .dockerenv
drwxr-xr-x    2 root     root          4096 Jul 11 17:29 bin

-rwxr-xr-x    1 root     root       8532786 Jul 24 17:22 myapp
/ # ./myapp 
/bin/sh: ./myapp: not found
/ # myapp

/bin/sh: myapp: not found
...

Troubleshooting #3

If docker run shows that app started with CMD doesn't have access privileges, it will output an error similar to this:

error TS5033: Could not write file '/home/node/myapp/build/index.js': EACCES: permission denied, open '/home/node/myapp/build/index.js'.

To find out the permissions on the /home/node/myapp/ you can temporarily change CMD app in Dockerfile:

CMD [ "ls", "-la", "/home/node/myapp" ]

Now rebuild the image and run the container - the output will show owners of that directory and files in it:

$ docker build -t bkomazec/myapp .
$ docker run --user node --rm -it --name running-myapp bkomazec/myapp


docker start


To start a container use docker start. In the following example container name is my-postgres:

$ docker start my-postgres
my-postgres

docker stop


To stop running one or more containers use docker stop:

$ docker stop my_service_postgres_1
my_service_postgres_1


docker image

$ docker image --help

Usage:  docker image COMMAND

Manage images

Commands:
  build       Build an image from a Dockerfile
  history     Show the history of an image
  import      Import the contents from a tarball to create a filesystem image
  inspect     Display detailed information on one or more images
  load        Load an image from a tar archive or STDIN
  ls          List images
  prune       Remove unused images
  pull        Pull an image or a repository from a registry
  push        Push an image or a repository to a registry
  rm          Remove one or more images
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE

Run 'docker image COMMAND --help' for more information on a command.

---

docker image ls


$ docker image ls --help

Usage:  docker image ls [OPTIONS] [REPOSITORY[:TAG]]

List images

Aliases:
  ls, images, list

Options:
  -a, --all             Show all images (default hides intermediate images)
      --digests         Show digests
  -f, --filter filter   Filter output based on conditions provided
      --format string   Pretty-print images using a Go template
      --no-trunc        Don't truncate output
  -q, --quiet           Only show numeric IDs


To list IDs of all images:

$ docker image ls -aq


docker image rm 


$ docker image rm --help

Usage:  docker image rm [OPTIONS] IMAGE [IMAGE...]

Remove one or more images

Aliases:
  rm, rmi, remove

Options:
  -f, --force      Force removal of the image
      --no-prune   Do not delete untagged parents


To delete all images:

$ docker image rm $(docker image ls -aq)


---

docker images


To see which images are present locally, use docker images:

$ docker images --help

Usage: docker images [OPTIONS] [REPOSITORY[:TAG]]

List images

Options:
  -a, --all             Show all images (default hides intermediate images)
      --digests         Show digests
  -f, --filter filter   Filter output based on conditions provided
      --format string   Pretty-print images using a Go template
      --no-trunc        Don't truncate output
  -q, --quiet           Only show numeric IDs


Example:

$ docker images
REPOSITORY           TAG                  IMAGE ID            CREATED             SIZE
my_app                      latest               477db2641216        12 minutes ago      193MB
<none>                    <none>               7f82c84cc05a        12 minutes ago      193MB




docker volume 


$ docker volume

Usage:  docker volume COMMAND

Manage volumes

Commands:
  create      Create a volume
  inspect     Display detailed information on one or more volumes
  ls          List volumes
  prune       Remove all unused local volumes
  rm          Remove one or more volumes

Run 'docker volume COMMAND --help' for more information on a command.


---

docker volume ls 


$ docker volume ls --help

Usage:  docker volume ls [OPTIONS]

List volumes

Aliases:
  ls, list

Options:
  -f, --filter filter   Provide filter values (e.g. 'dangling=true')
      --format string   Pretty-print volumes using a Go template
  -q, --quiet           Only display volume names

---


$ docker volume ls
DRIVER              VOLUME NAME
local               1a2a9d0f43ce94ad1e176f9bb318f46829fcd34354d4d648d70434efa0f43f60
local               1a66b905bcd4be936b8df26cacf018d7f863e758773a11be5faf9d9949311eb0
local               1c6af16b8d8b1041ad3a46e3910bde9121b64cfae65f8299cedd81793d8fce37
...


$ docker volume ls -q
1a2a9d0f43ce94ad1e176f9bb318f46829fcd34354d4d648d70434efa0f43f60
1a66b905bcd4be936b8df26cacf018d7f863e758773a11be5faf9d9949311eb0
1c6af16b8d8b1041ad3a46e3910bde9121b64cfae65f8299cedd81793d8fce37

---

docker volume rm


$ docker volume rm --help

Usage:  docker volume rm [OPTIONS] VOLUME [VOLUME...]

Remove one or more volumes

Aliases:
  rm, remove

Examples:

$ docker volume rm hello
hello


Options:
  -f, --force   Force the removal of one or more volumes
---

To remover all volumes:

$ docker volume rm $(docker volume ls -q)



TBC...

References


Lifecycle of Docker Container
Hey Docker! Why do you hate Windows so much?
Exploring Docker container's file system

No comments: