Docker Misc Q&A

Last update: 2026-05-13 23:59:17 +0800 CST
tags: Docker

Fun things about Docker.

Refer to the host machine’s IP address from container #

  • For MacOS host + Docker Desktop, the name docker.for.mac.host.internal resolves to the IP address of the virtual NIC installed on MacOS, automatically without any need of configuration. Of course the VM layer (https://github.com/linuxkit/linuxkit/blob/master/examples/docker-for-mac.md) still exist, but at least you have the IPv4 routing working delivering real TCP.
  • For Linux host + Docker engine, the docker run and create command accepts a --add-host=name:<ip> flag to add a <ip> name in container’s /etc/hosts. A special literal value host-gateway can be used for <ip> to refer to the IP address on the virtual NIC in the host’s Linux kernel. (the Docker engine will set it up). So eventually you get a line like 172.0.0.1 name.
sh
docker run --name gugu -it --entrypoint bash --user jose --add-host=hostgg:host-gateway -v $AA:$AA -v $BB:$CC -e DISPLAY=:0 -e XAUTHORITY=$CC kk

# in the container
getent hosts hostgg
172.17.0.1      hostgg

Reuse component in docker compose.yaml #

Use the YAML anchor/merge syntax for reusable pieces of configuration in docker compose yaml:

yaml
networks:
  gugunet:
    driver: bridge
    enable_ipv6: false
    ipam:
      driver: default
      config:
        - subnet: 99.99.99.0/24
          gateway: 99.99.99.1

x-hdfs-commons: &hdfs-commons
  # hadoop launcher scripts requires bash, don't use alpine.
  image: ubuntu:latest
  volumes:
    - ../rofiles/zulu17.58.21-ca-jdk17.0.15-linux_aarch64:/opt/jdk:ro
    - ../rofiles/hadoop-3.4.1:/opt/hadoop:ro
    - ./core-site.xml:/opt/hadoop/etc/hadoop/core-site.xml:ro
#    - ./hdfs-site.xml:/opt/hadoop/etc/hadoop/hdfs-site.xml:ro
    - ./hadoop-logs:/tmp/hadoop-logs
  environment:
    - JAVA_HOME=/opt/jdk
    - PATH=$PATH:/opt/jdk/bin:/opt/hadoop/bin
    - HADOOP_LOG_DIR=/tmp/hadoop-logs


services:
  hdfs-name-node:
    <<: *hdfs-commons
    networks:
      gugunet:
        ipv4_address: 99.99.99.100
    command: bash -c "hdfs namenode -format && hdfs --daemon start namenode && sleep infinity"
  hdfs-data-node-1:
    <<: *hdfs-commons
    command: bash -c "hdfs --daemon start datanode && sleep infinity"
    networks:
      gugunet:
        ipv4_address: 99.99.99.101

Setting Envvars #

Rule of thumbs:

  • Dockerfile ENV can only refer to other ENV or ARG, and can’t refer to any shell variable: neither from guest’s shell nor host’s shell. It also won’t work if your value of your envvar is computed by a command. If that’s okay for you, stick with 1 and 2.
  • otherwise, escalate to 3 and 4 (for an example).
  1. Dockerfile ENV command

    this method make containerd to add the specified env var upon fork-exec of any process that runs as part of the container. So works for both entrypoint process and any docker exec into a running container, and has nothing to do with a shell nor any shell rc.

    The only variable substitutions supported by ENV is ARG and other ENV, so $PATH won’t work (neither do any other well-known unix env vars)

  2. docker run -e or compose.yaml environment

    The mechanism is identical to the Dockerfile ENV command - non-shell entrypoint see the envvar, non-shell exec also see the envvar - except that

    • it’s valid for a one-shot container and all later docker exec into it.
    • All expansion is done by the host’s shell. No variable allowed except the host shell’s ones.
  3. Dockerfile RUN command to modify shell rc

pros:

  • we are in a real guest machine’s shell environment, values of env vars can be the output of a process e.g. adding a line export foo="$(...)" to rc. This was never possible for 1 and 2.
  • docker exec command and container entrypoint, if both shell, now sees the same envvar.

cons:

  • you need to build a new imagel
  • this won’t work if your entrypoint or exec command is not a shell.

Also docker images of most linux distros uses non-login bash. Be sure you modify the right system or user level rc, not the profiles.

  1. export in entrypoint init script

This is just a weakening version of 3. The exported env vars can only be observed subprocess of that init script; and docker exec sees nothing.

Limiting the visibility of variable is always a good thing though.

  1. export in a standalone script prepared for docker exec -it ... script.sh

    This setup only makes sense if the entrypoint just sleep infinity and you are about to docker exec into the container to play with the isolated environment by typing shell commands; All subprocess of the init script won’t see the env var (only you source it), but again, make sense for sleep infinity.