Estou começando a entender melhor como os dockers funcionam, e tive um problema enorme em entender como um container acessa outro. Por exemplo precisei criar um container com PHP 8.1 e um container com PostgreSQL. Ambos são visíveis ao host, porem eles não se comunicam, foi então que entendi que eles precisam estar na mesma rede para que possam ser acessíveis facilmente

Para quem está começando, assim como eu, à usar docker, entender a visibilidade dos container é um problema. Principalmente porque você consegue enxergar o container do host, então seria meio óbvio que 2 containers também tivessem acesso entre eles. Porem não é bem assim.

Consegui começar a entender o funcionamento de forma mais simples, quando comecei a utilizar do docker compose para criar meus containers, e aconselho fortemente você a usa-lo também.

Para que os containers possam se comunicar, você precisa coloca-los na mesma rede, e a forma mais simples que eu achei para fazer isso, é definir o nome da rede que o container vai ingressar. Nada de comandos complexos.

Eu defini que meu serviço entraria na rede dockernet, e defini como essa rede funciona

version: '3.5'
services:

  postgres: 
    container_name: postgres
    image: postgres:11
    environment:
      - PGDATA=/var/lib/postgresql/11
      - POSTGRES_PASSWORD=senha
      - POSTGRES_USERNAME=postgres
    volumes:
       - /var/lib/postgresql/11:/var/lib/postgresql/11
    ports:
      - "5432:5432"
    restart: always
    networks:
      - dockernet

networks:
  dockernet:
    name: dockernet
    driver: bridge

Esse é meu docker-compose.yml

Veja que defini que o serviço postgres, vai ingressar na rede dockernet, e logo após eu defino o que é essa rede

Agora posso criar outros serviços, por exemplo o PHP

version: '3.5'
services:

  php:
    container_name: php8.1-apache
    build: 
      context: ./php
      dockerfile: Dockerfile
    ports:
      - "80:80"
      - "443:443"
    volumes:
     - ~/www/:/var/www/html/
    environment:
      - ALLOW_OVERRIDE=true
    networks:
      - dockernet

networks:
  dockernet:
    name: dockernet
    driver: bridge

Veja que a definição da rede é a mesma, e eu também ingressei o serviço php à mesma rede.

E prontinho, agora os container conseguem se comunicar, usando o nome do serviço como host, ficando SERVICO_NOME.NOME_REDE. No meu caso, postgres.dockernet. Ou como eles estão na mesma rede, somente postgres.

$host= 'postgres.dockernet';
$db = 'andor';
$user = 'postgres';
$password = 'senha';
$dsn = "pgsql:host=$host;port=5432;dbname=$db;";

E feito!