Docker behavior can be managed at daemon and client levels. These configurations can be executed using command-line arguments, environment variables, or definitions on configuration files.
Customizing the Docker daemon
Docker daemon behavior is managed by various configuration files and variables:
- key.json: This file contains a unique identifier for this daemon; in fact, it is the daemon's public key that uses the JSON web key format.
- daemon.json: This is the Docker daemon configuration file. It contains all its parameters in JSON format. It has a key-value (or list of values) format in which all the daemon's flags will be available to modify its behavior. Be careful with configurations implemented on the systemd service file because they must not conflict with options set via the JSON file; otherwise, the daemon will fail to start.
- Environment variables: HTTPS_PROXY, HTTP_PROXY, and NO_PROXY (or using lowercase) will manage the utilization of Docker daemon and the client behind the proxies. The configuration can be implemented in the Docker daemon systemd unit config files using, for example, /etc/systemd/system/docker.service.d/http-proxy.conf, and following the content for HTTPS_PROXY (the same configuration might be applied to HTTP_PROXY):
[Service]
Environment="HTTPS_PROXY=https://proxy.example.com:443/" "NO_PROXY=localhost,127.0.0.1,docker-registry.example.com,.corp"
Be careful with the key.json file while cloning virtual machines because using the same keys on different daemons will result in strange behaviors. This file is owned by system administrators, so you will need to use a privileged user to review its content. This JSON file contains Docker Daemon's certificate in JSON Web Key format. We can just review the key.json file's content using the cat and jq commands (jq is not required, but I used it to format output. This command will help with JSON files or JSON output):
$ sudo cat /etc/docker/key.json |jq{
"crv": "P-256",
"d": "f_RvzIUEPu3oo7GLohd9cxqDlT9gQyXSfeWoOnM0ZLU",
"kid": "QP6X:5YVF:FZAC:ETDZ:HOHI:KJV2:JIZW:
IG47:3GU6:YQJ4:YRGF:VKMP",
"kty": "EC",
"x": "y4HbXr4BKRi5zECbJdGYvFE2KtMp9DZfPL81r_qe52I",
"y": "ami9cOOKSA8joCMwW-y96G2mBGwcXthYz3FuK-mZe14"
}
The daemon configuration file, daemon.json, will be located by default at the following locations:
- /etc/docker/daemon.json on Linux systems
- %programdata%\docker\config\daemon.json on Windows systems
In both cases, the configuration file's location can be changed using --config-file to specify a custom non-default file.
Let's provide a quick review of the most common and important flags or keys we will configure for Docker daemon. Some of these options are so important that they are usually referenced in the Docker Certified Associate exam. Don't worry; we will learn about the most important ones, along with their corresponding JSON keys, here:
Daemon argument | JSON key | Argument description |
-b, --bridge string | bridge | Attach containers to a network bridge. This option allows us to change the default bridge behavior. In some cases, it's useful to create your own bridge interfaces and use the Docker daemon attached to one of them. |
--cgroup-parent string | cgroup-parent | Set the parent cgroup for all containers. |
-D, --debug | debug | This option enables debug mode, which is fundamental to resolving issues. Usually, it's better to stop Docker service and run the Docker daemon by hand using the -D option to review all dockerd debugging events. |
--data-root string | data-root | This is the root directory of the persistent Docker state (default /var/lib/docker). With this option, we can change the path to store all Docker data (Swarm KeyValue, images, internal volumes, and so on). |
--dns list | dns | This is the DNS server to use (default []). These three options allow us to change the container DNS behavior, for example, to use a specific DNS for the container environment. |
--dns-opt list | dns-opt | These are the DNS options to use (default []). |
--dns-search list | dns-search | These are the DNS search domains to use (default []). |
--experimental | experimental | This enables experimental features; don't use it in production. |
-G, --group string | group | This is the group for the Unix socket (default docker). |
-H, --host list | host | This is the option that allows us to specify the socket(s) to use. |
--icc | icc | This enables inter-container communication (default true). With this option, we can disable any container's internal communications. |
--ip IP | ip | This is the default IP when binding container ports (default 0.0.0.0). With this option, we can ensure that only specific subnets will have access to container-exposed ports. |
--label list | label | Set key=value labels to the daemon (default []). With labels, we can configure environment properties for container location when using a cluster of hosts. There is a better tagging method you can use when using Swarm, as we will learn in Chapter 8, Orchestration Using Docker Swarm. |
--live-restore | live-restore | This enables the live restoration of Docker when containers are still running. |
--log-driver string | log-driver | This is the default driver for container logs (default json-file) if we need to use an external log manager (ELK framework or just a Syslog Server, for example). |
-l, --log-level string | log-level | This sets the logging level (debug, info, warn, error, fatal) (default info). |
--seccomp-profile string | seccomp-profile | This is the path to the seccomp profile if we want to use anything other than the default option. |
--selinux-enabled | selinux-enabled | Enables SELinux support. This option is crucial for production environments using Red Hat Linux/CentOS. It is disabled by default. |
-s, --storage-driver string | storage-driver | This is the storage driver to use. This argument allows us to change the default driver selected by Docker. In the latest versions, we will use overlay2 because of its stability and performance. Other options include aufs, btrfs, and devicemapper. |
--storage-opt list | storage-opts | Storage driver options (default []). Depending on the storage driver used, we will need to add options as arguments, for example, using devicemapper or for specifying a maximum container size on overlay2 or Windows filter (MS Windows copy-on-write implementation). |
--tls | tls | This option enables TLS encryption between client and server (implied by --tlsverify). |
--tlscacert string | tlscacert | Trust certs signed only by this CA (default ~/.docker/ca.pem). |
--tlscert string | tlscert | This is the path to the TLS certificate file (default ~/.docker/cert.pem). |
--tlskey string | tlskey | This is the path to the TLS key file (default ~/.docker/key.pem). |
--tlsverify | tlsverify | Use TLS and verify the remote. |
Logging information in container environments can be deployed using different layers of knowledge. As shown in the previous table, Docker daemon has its own logging configuration using --log-driver. This configuration will be applied to all containers by default if we do not specify any configuration during container execution. Therefore, we can redirect all container logs to some remote logging system using the ELK framework, for example (https://www.elastic.co/es/what-is/elk-stack), while some specific containers can be redirected to another logging backend. This can also be applied locally using different logging drivers.
Docker client customization
The client will store its configuration under the users' home directory on .docker. There is a config file where the Docker client will look for its configurations ($HOME/.docker/config.json on Linux or %USERPROFILE%/.docker/config.json on Windows). In this file, we will set a proxy for our containers if it's needed to connect to the internet or other external services, for example.
If we need to pass proxy settings to containers upon startup, we will configure the proxies key in .docker/config.json for our user, for example, using my-company-proxy:
"proxies":
{
"default":
{
"httpProxy": "http://my-company-proxy:3001",
"httpsProxy": "http://my-company-proxy:3001",
"noProxy": "*.test.example.com,.example2.com"
}
}
These configurations can be added as arguments when starting up the Docker container, as follows:
--env HTTP_PROXY="http://my-company-proxy:3001"
--env HTTPS_PROXY="https://my-company-proxy:3001"
--env NO_PROXY="*.test.example.com,.example2.com"
We will see what "environment option" means in Chapter 3, Running Docker Containers. Just keep in mind that, sometimes, our corporate environment will need applications to use proxies and that there are methods to configure these settings, either as user variables or using client configurations.
Other client features, such as experimental flags or output formatting, will be configured in the config.json file. Here is an example of some configurations:
{
"psFormat": "table {{.ID}}\\t{{.Image}}\\t{{.Command}}\\t{{.Labels}}",
"imagesFormat": "table {{.ID}}\\t{{.Repository}}\\t{{.Tag}}\\t{{.CreatedAt}}",
"statsFormat": "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}"
}