How to make an entry in /etc/hosts when starting a container?

When starting the container, I substitute docker-php-entrypoint.sh. There is code in the file that writes to /etc/hosts ip host.docker.internal

#!/bin/sh
set -e


HOST_DOMAIN="host.docker.internal"
if ! ping -q -c1 $HOST_DOMAIN > /dev/null 2>&1
  then
 HOST_IP=$(ip route | awk 'NR==1 {print $3}')
 # shellcheck disable=SC2039
 echo -e "$HOST_IP\t$HOST_DOMAIN" >> /etc/hosts
fi


#first arg is `-f` or `--some-option`
if [ "${1#-}" != "$1" ]; then
  set -- php-fpm "$@"
fi


exec "$@"

I also change the user that runs the container from root to app

FROM php:8.1-cli-alpine
....................................

COPY ./common/entrypoint.sh /usr/local/bin/docker-php-entrypoint
RUN chmod +x /usr/local/bin/docker-php-entrypoint

RUN addgroup -g 1000 app && adduser -u 1000 -G app -s /bin/sh -D app

WORKDIR /app

USER app

In docker-compose.yml

php-cli:
build:
  context: ./project/docker
  dockerfile: development/php-cli/dockerfile
volumes:
  - ./project:/app

Launching the container is terminated with the error “Permission denied”

In general, it is clear that the app user does not have permissions to write to /etc/hosts.

I tried to run docker-php-entrypoint via RUN right after setting execution rights and before creating the app user - error “Read-only file system”.
I tried to use su in docker-php-entrypoint, no result.

How can I solve this problem, so that the container is started from app, but it is possible to make an entry in /etc/hosts?

Seems like a permission problem. Have you tried setting read-write permissions for the user/group on the file?

Try

sudo chown root:1000 /etc/hosts
sudo chmod 664 /etc/hosts

This changes the group ownership to the user group with ID 1000 and sets the permissions so that both the owner (root) and group (1000) can read and write, while others can only read. (ChatGPT)

A bit cleaner would be this, but it’s not always available

setfacl -m u:app:rw /etc/hosts

In general this does have security implications! If some can abuse your app and make changes to the file, it might be a security risk.

Seems like a permission problem.

Of course it’s a permission problem, but I can’t figure out how to solve it.
I’ll try your way, maybe it will help.

The sudo requires a password, when launching the container you need to launch without a password.
This is required on the local server, the production server will not use this code.

Nothing helped.

Caused an error

RUN chown root:1000 /etc/hosts:
0.477 chown: changing ownership of ‘/etc/hosts’: Read-only file system

I tried doing all this in a Dockerfile

This is a good example for doing something that shouldn’t be done at all with Docker. As you already knew, app user can’t write the hosts file, but even if it could, it doesn’t need to. In old Docker versions that didn’t use buildkit by default, you could write the hosts file during build, but I never needed it. Buildkit uses a different method to build images running (If I remember correclty) runc and the hosts file is not writeable.

What you need is --add-host hostname:ip passed to docker run or extra_hosts in compose.

But why do you want to refer to the container’s IP address using host.docker.internal? That is pointed to the physical host through a proxy in Docker Desktop and you can implement a similar feature on Linux without the Desktop as well:

By the way the hosts file is not actually part of the container’s filesystem. It is mounted into it. You can use docker container inspect to get its path:

docker container inspect CONTAINER_NAME --format '{{ .HostsPath }}'
1 Like

Hi, in case you or anybody else will face this neccessity again.

I’ve recently published an app that keeps /etc/hosts in sync to docker state by labels or by environment variables.

Like VIRTUAL_HOST=hello.local

When container with this environment variable defined is running for the first time, respected entry will be added to /etc/hosts

If you want to map by VIRTUAL_HOST, make sure you set wilder-nginx as a provider. Default provider is traefik

https://hub.docker.com/r/papeviso/dresmon

Perhaps you will find this as a clean solution.

Doesn’t support Windows as a host machine

I have something like that too based it on jwilder/docker-gen and I similarly supported only Linux, possibly MacOS, but never tried it there. However, in this topic the goal was to edit the hosts file inside the container, not on the host. Changing it inside the container is what the add-host parameter is for. I still thank you for sharing your image.

then I’ll give you another few hints:

  proxy:
...
    depends_on:
      - dnsmasq
    networks:
      local-proxy:
        ipv4_address: 172.30.0.2
...

  dnsmasq:
    image: andyshinn/dnsmasq:2.78
    command: -d --address=/.local/172.30.0.2
    networks:
      local-proxy:
        ipv4_address: 172.30.0.3
...

also you can name your service verbatim matching the domain name you with it to be resolved to for it’s siblings

  app.local:
...
  client:

from withing client, app.local will be resolved to conainers of app.local service

long story short, you most definitely don’t need to maintain /etc/hosts of your container, there are cleaner mainstream solutions

I get that but this is still not what this topic was about. Docker has its own DNS server so for container to container communication you don’t need to create one manually. You can also use network aliases so don’t have to use the name of the service or container, you can have any alias you like without knowing the IP address.

However, this topic was about accessing the Docker host. You could probably still use a new DNS server to support that hostname in containers but why would you run a DNS server for that when --add-host adds that host and IP without any additional service?

So it seems to me that a DNS server would be useful only when you want to use that from the host too, and resolve internal domain names of containers so you don’t have to edit the hosts file on the Docker host.