Docker commands:

  • docker run [image name]
    • is like docker create + docker start
    • -it – interactive; will connect to the standard input of the container – thus allowing for interacting using the keyboard
    • we can run docker run -it [image name] sh – this will override the default image command and just start a shell
      • usually, you run the container with its default command and then perform a docker exec to run anything additional, but using above you can override the default command – you can use whatever you may need instead of sh, sh is just an example
    • -v [local machine directory]:[docker container directory] – mounts a volume
      • btw, $(pwd) – will return a reference to present working directory
      • Named volumes (store in Docker-defined location) are specified by name and optionally followed by a colon and a container path (name:/container/path).
        If the name looks like an absolute path and there’s no colon, it’s unconventional and might lead to confusion, but Docker will treat it as a named volume. (Convenient name: abc. Misleading name name: /abc)
      • Bind mounts (host folder to container folder) are specified by an absolute path on the host, followed by a colon and a container path (/host/path:/container/path).
      • An anonymous volume is specified simply as a container path, like this: docker run -v /var/qwe some_image. Docker will then create an anonymous volume and mount it to /var/qwe inside the container. The exact storage location of the volume on the host is managed by Docker and is not intended to be directly accessed or managed by the user. An anonymous volume is a type of volume that doesn’t have a name you define. It’s created by Docker with a randomly generated name (or identifier) and is mainly used for ensuring data persistence across container restarts for that specific container instance or for when the specific data doesn’t need to be named or reused across containers.
        • Container-bound: While they persist beyond the lifecycle of the container, anonymous volumes are typically associated with the container they were created with. They’re not as easily managed or reused as named volumes.
        • Automatic Cleanup: When you remove a container with the docker rm -v command, Docker also removes any anonymous volumes associated with that container, helping to avoid orphaned volumes.
        • Use Case:
          • Anonymous volumes can be useful for temporary data that’s needed during a container’s runtime but not beyond it, and when you don’t need to name or manage the volume outside of Docker’s automatic handling.
          • They are a kind of placeholder for a folder that is inside the container (we kind of declare that inside the container this folder will be available). If that location would have to be overridden by a mapping volume – now it will not be. (good to be used for example in case of node_modules folder – when we want to map everything but it, then we create first an anonymous volume like -v /node_modules
      • Best practices for all types of volumes:
        • Named: docker run -v some_volume:/tmp/qwe some_image
        • Bind: docker run -v /var/asd:/tmp/qwe some_image
        • Anonymous: docker run -v /tmp/qwe some_image
        • Tmpfs: docker run –tmpfs /tmp/qwe:size=100m,mode=700 some_image
    • –tmpfs – double dash! mounts a RAM-only volume. All the data in the volume is ephemeral and disappears as soon as the container is stopped. For ex: docker run –tmpfs /path/in/container:size=100m,mode=700 some_docker_image
    • -p [source machine port number]:[container port number] (for ex. docker run -p 8080:8080 alpine)
      • Port mapping. Forward any request to the machine running the docker container to the container itself and specifically to the port specified in the mapping. This covers requests targeted towards the container. By default, there are no limitations vice versa – from the container to the outside world. The port mapping is to be used only when using an image – it has nothing to do with the image configuration.
      • Port numbers may be different
    • -e [variable_name=variable_value] – add an environment variable to the image to be available in the container
  • docker create [image name]
    • creates the container without running it
  • docker start [container identifier]
    • starts an already created container
  • docker start -a [container identifier]
    • -a makes it print the logs too; -a stands for attach
  • docker logs [container identifier]
    • prints the logs of a running container
  • docker stop [container identifier]
    • SIGTERM (clean stop) – basically telling the container to stop. If not done in 10 secs will issue the kill command
  • docker kill [container identifier]
    • SIGKILL – a command to shut down right now
  • docker exec -it [container identifier] [command]
    • execute a command in an already running container¬
    • -it is the same as -i and -t; these are required for interactive terminal; -t is for nicely formatting of the terminal
    • docker exec -it [container identifier] sh
      • will run the sh command processor / command shell (there are also others: bash, powershell, zsh etc.) and allow for more commands to be used
        • usually, sh is included
      • use Ctrl+D to exit
  • docker build .
    • pay attention to the tailing . (dot)
      • The dot is specifying the build context – the set of files we want to encapsulate in container
    • this command builds an image from a Dockerfile
      • The Dockerfile is the name of the actual file with instructions on how to build the image
        • Its main components are:
          • FROM
            • defines the original image used. For example, alpine (a Linux image with only 5MB in size)
          • EXPOSE [port number]
            • Does not do anything on local environment automatically. It is an instruction for CI/CD for port mapping – for ex. in ElasticBeanstalk.
            • The EXPOSE instruction doesn’t actually publish the port. It functions as a type of documentation between the person who builds the image and the person who runs the container, about which ports are intended to be published
          • RUN
            • The command to be run on the while preparing the image
          • CMD
            • The command to be run by default when running a container using the image we are creating
          • COPY
            • Used to copy files from local machine to the temporary container used during the build process
            • Syntax COPY [path on your machine] [path in the container] (for ex. COPY ./ ./)
              • The path is relative to the build context
                • For ex. If command pwd returns C:/some_path, running docker build . will make the path C:/some_path the build context. So when I use the COPY command, the ./ in it will refer to C:/some_path
            • During the build Docker “observes” modifications in copied files and if it spots any files changed between the builds – COPY instruction will trigger creation of build-related containers for every follow up step, including the COPY step too
          • WORKDIR
          • WORKDIR [some path]
          • Makes any command following this instruction to use the path specified by default
      • When modifying the Dockerfile and re-building an image – Docker will use cache of intermediate images used for building process. Specifically, that will be done for all the steps starting with the modified line.
        • Conclusion: The lower in Dockerfile you add your changes – the better. As this will make Docker use cache more while building the image.
    • Use -f for specifying a custom file name: docker build -f Dockerfile.dev .
    • Use -t for adding a tag to the image created. The tag must have the following format: [your docker id]/[project name]:[version] (for example: vitalieb905/redis:latest)
      • Full command will be: docker build -t vitalieb905/redis:latest .
        • Don’t miss the dot at the end!
        • You can skip the latest – the latest will be added by default
        • Technically only the version is the actual tag, all the rest is the repo/project name
  • docker attach [container identifier] – attaching to STDIN, STDOUT and STDERR of the primary process (with process id of 1) inside the container; there is no way to attach to any other process inside the container using attach
  • docker commit -c “CMD ‘redis-server'” 3369cb45b69a
    (docker commit -c ‘CMD [“redis-server”]’ 3369cb45b69a) for Linux/MacOS
    • Alternative way of creating images – without using a Dockerfile
    • Create a container, run a command and generate an image off that. The image is created off a running container!
    • The -c is defining the default command for the newly created image
    • The 3369cb45b69a is the container identifier obtained using docker ps

Multi-step build process

When creating a Dockerfile we define each step by adding as [step name] after the FROM [image name].
For ex.: FROM alpine as minimum
A successor step (block) has to just start with FROM.
To copy the output of a previous step into current one, use
COPY –from=[previous step name] [directory in previous image] [directory in current image]
For example:
COPY –from=minimum /etc/111 /usr/222
Example from https://docs.docker.com/build/building/multi-stage/#use-multi-stage-builds

syntax=docker/dockerfile:1

FROM golang:1.21
WORKDIR /src
COPY [[EOF ./main.go
package main

import "fmt"

func main() {
fmt.Println("hello, world")
}
EOF
RUN go build -o /bin/hello ./main.go

FROM scratch
COPY --from=0 /bin/hello /bin/hello
CMD ["/bin/hello"]
Dockerfile

Docker compose

Separate component installed along with Docker. Make starting multiple containers much easier.
Main file of it is docker-compose.yml. docker-compose.yml is interpreted by docker-compose CLI.
BTW: a dash (-) in a YAML file is for specifying an array

  • When 2 containers are started using docker compose there is no need to specify any port mapping between them – they can access each other by default
    • Containers can refer to each other by the name of the container (service) from the docker-compose.yaml
  • docker-compose up
    • Will automatically run the docker-compose.yaml configuration
    • –- build – is added for: rebuilding the images + run them
    • -f allows for specifying a custom-named docker-compose file: docker-compose -f docker-compose-test.yml up
    • -d – running a group of containers in the background (detached mode)
      • docker-compose down would stop such a setup
  • docker-compose ps
    • Same thing as docker ps – is used for status check. But! Needs to be run in the directory with docker-compose.yaml

In docker-compose.yml:

  • An environment variable is set at the time the container is spined up – the image contains no data about environment variables
  • Environment variables may be defined in 2 ways:
    • [variable name]=[value]
    • [variable name] – this time the value will be taken from the machine docker-compose up is run on

Docker compose 4 restart policies:

  1. “no” – don’t attempt to restart. Important! The option “no” – needs to be in quotes – because in YAML files no is interpreted as false
  2. always – regardless of the reason – restart it
  3. on-failure – only restart if stopped with an error code. If you exit with something like process.exit(0) – it won’t restart because this is not considered an error
  4. unless-stopped – restart unless stopped by force. This one is a bit confusing. It acts just like always does. The key difference is that:
    • if you stopped a container using docker stop or docker kill and afterwards the system restarted or daemon restarted – the container will not be restarted
    • While with always it will be – the fact that you stopped a container that has the restart policy set to always in a manual way using docker stop or docker kill will not affect the requirement for it to be always available after a potential system restart or daemon restart

LEAVE A REPLY

Please enter your comment!
Please enter your name here

This site uses Akismet to reduce spam. Learn how your comment data is processed.