Docker tips, tricks and gotchas…

I have been doing some test and exploration putting Docker containers together via docker-compose. Here are some tricks not mentioned in most cheat sheets but are very valuable in my journey as I struggle with it. I will keep trying to update this.

Networking: 

  • Container IP:
    • docker inspect -f "{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" 
    • then add 4 alphanumeric of the containers ID to get the IP.
  • Apache in Docker container needs to be run using foreground process for it to work :e.g.
    • CMD apachectl -D FOREGROUND
  • A common problem I run into a LOT is, inter docker communication. Which seems SHOULD be straight forward but insanely annoying to debug somehow.
    • nslookup from the dnsutils repo seems to help clear the fog somewhat to ensure at least they can NameService resolve to other containers!

Management:

  • Always use docker ps -a instead of docker ps  as the later does not show stopped containers. 
  • docker rm is for container and docker rmi is for images
    • If you are developing and have to debug image/container as part of the compose, best to have a simple bash script like this to quickly remove image/container:
      • #!/usr/bin/env bash
        # bach script to automatically remove the image/container to
        docker rm DC_LORIS22Configurator_v0.4
        docker rmi dockerbuilds_chrome:latest
    • Alternatively, force newer image and ignore cache. HOWEVER, this is non-selective i believe so if you have a compose with many images, it might be more efficient to go first.
          --no-cache              Do not use cache when building the image.
          --pull                  Always attempt to pull a newer version of the image.
  • To build a custom Docker image file, make sure to specify the context
    • docker build -f Dockerfile.LORIS21.Ubuntu18 ../../
    • If the context is not specified properly, the copying file operations might fail.

Docker File:

  • RUN vs CMD and WAIT for​_ service to be up before running:
    • When docker compose run all things, they don’t care about whether it is fully ready ready. They launch and assume ready… The Container needs to be robust enough to check this before fully run. One dumb/lazy way to solve this is to delay the launch. E.g. at ENTRYPOINT/CMD ensure there is a sleep 1 minute or something. DO NOT DO THIS IN RUN as that is executed at image building and will not affect deployment whatsoever…
  • This is the defacto guide on Docker ARG/ENV/.ENV variables https://vsupalov.com/docker-arg-env-variable-guide/
    • My approach was actually set ARG using .env at DockerCompose level, use ARG to set ENV at DockerFile level, and then in my app/script load ENV. This seems SUPER convoluted but it give the flexibility that you can reuse DockerFile (via ARG), reuse app/script via ENV variable, and have a lot flexibility but maintaining variable naming consistency can be annoying .
  • One issue I found commonly cause my ARG (loaded from Compose/ENV) to not work is because I forgot to declare the ARG in its own line ahead of time….

Docker Compose:

  • This stackoverflow thread give a very good quick insight into how to persist volumes in the Docker Compose context and Docker File context: https://stackoverflow.com/questions/40905761/how-do-i-mount-a-host-directory-as-a-volume-in-docker-compose 
  • Make sure to wait for services to fully start (i.e. depend_on merely LAUNCHES services) before calling them.
  • When specifying volume for services, make sure there is no space after column
    volumes:
    - lorisdbvolume:/var/lib/mysql

Debugging:

  • Ctrl + P + Q puts interactive Docker sessions to background
  • Docker stop all container:
    • docker stop $(docker ps -a -q)
  • Avoid debugging dockerfile and dockercompose at the same time.
    • Get dockerfile working by itself before putting them together.

MySQL

  • Not exactly docker related but I stuck on this while trying to connect to mysql in a docker bash for a long long time: the proper syntax is something like this:
    • mysql $LorisMySQLDatabase -hlorismridb -p3306 -u$LorisMySQLUser -p$LorisMySQLUserPassword
    • Notice that port cannot be part of the host name, at it will not resolve properly and lead to MySQL Client Error 2005/2003.
    • Use bash environmental variable (after securing the container).
    • Note that the h/p/u/p flags are always immediately proceeding.