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.internalresolves 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 runandcreatecommand accepts a--add-host=name:<ip>flag to add a<ip> namein container’s/etc/hosts. A special literal valuehost-gatewaycan 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 like172.0.0.1 name.
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 hostggReuse component in docker compose.yaml
#
Use the YAML anchor/merge syntax for reusable pieces of configuration in docker compose 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.101Setting Envvars #
Rule of thumbs:
- Dockerfile
ENVcan only refer to otherENVorARG, 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).
Dockerfile
ENVcommandthis method make
containerdto 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 anydocker execinto a running container, and has nothing to do with a shell nor any shell rc.The only variable substitutions supported by
ENVisARGand otherENV, so$PATHwon’t work (neither do any other well-known unix env vars)docker run -eorcompose.yamlenvironmentThe mechanism is identical to the Dockerfile
ENVcommand - non-shell entrypoint see the envvar, non-shellexecalso see the envvar - except that- it’s valid for a one-shot container and all later
docker execinto it. - All expansion is done by the host’s shell. No variable allowed except the host shell’s ones.
- it’s valid for a one-shot container and all later
Dockerfile
RUNcommand 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 execcommand 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.
exportin 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.
exportin a standalone script prepared fordocker exec -it ... script.shThis setup only makes sense if the entrypoint just
sleep infinityand you are about todocker execinto 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 forsleep infinity.