5

I would like to have an application, database and redis service running in a dev container where I'd be able to access my database and redis inside the container, application and on Windows, this is what currently works just as I wanted for my application and database:

.devcontainer.json:

{
  "name": "Node.js, TypeScript, PostgreSQL & Redis",
  "dockerComposeFile": "docker-compose.yml",
  "service": "akira",
  "workspaceFolder": "/workspace",
  "settings": {
    "typescript.tsdk": "node_modules/typescript/lib",
    "sqltools.connections": [
      {
        "name": "Container database",
        "driver": "PostgreSQL",
        "previewLimit": 50,
        "server": "database",
        "port": 5432,
        "database": "akira",
        "username": "ailuropoda",
        "password": "melanoleuca"
      }
    ],
    "editor.formatOnSave": true,
    "editor.codeActionsOnSave": {
      "source.fixAll": true
    }
  },
  "extensions": [
    "aaron-bond.better-comments",
    "dbaeumer.vscode-eslint",
    "esbenp.prettier-vscode",
    "mtxr.sqltools",
    "mtxr.sqltools-driver-pg",
    "redhat.vscode-yaml"
  ],
  "forwardPorts": [5432],
  "postCreateCommand": "npm install",
  "remoteUser": "node"
}

docker-compose.yml:

version: "3.8"

services:
  akira:
    build:
      context: .
      dockerfile: Dockerfile
    command: sleep infinity
    env_file: .env
    volumes:
      - ..:/workspace:cached

  database:
    image: postgres:latest
    restart: unless-stopped
    environment:
      POSTGRES_USER: ailuropoda
      POSTGRES_DB: akira
      POSTGRES_PASSWORD: melanoleuca
    ports:
      - 5432:5432
    volumes:
      - pgdata:/var/lib/postgresql/data

  redis:
    image: redis:alpine
    tty: true
    ports:
      - 6379:6379

volumes:
  pgdata:

Dockerfile:

ARG VARIANT="16-bullseye"
FROM mcr.microsoft.com/vscode/devcontainers/typescript-node:0-${VARIANT}

As you can see I already tried to achieve what I wanted to using networks but without success, my question is: How can I add Redis to my services while still being able to connect redis and database inside the application and on Windows?

3 Answers3

2

Switch all non-dev containers to network_mode: service:akira

version: '3.8'
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - ../..:/workspace:cached
    command: sleep infinity
  postgresql:
    image: postgres:14.1
    network_mode: service:akira
    restart: unless-stopped
    volumes:
      - ../docker/volumes/postgresql:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: postgres
      POSTGRES_USER: postgres
      POSTGRES_DB: pornapp
  redis:
    image: redis
    network_mode: service:akira
    restart: unless-stopped
    volumes:
      - ../docker/volumes/redis:/data

It seems this was the original configuration : https://github.com/microsoft/vscode-dev-containers/pull/523

But it was reverted back because if you rebuild the dev container while others servies are running, the port forwarding will break : https://github.com/microsoft/vscode-dev-containers/issues/537

Dawei67
  • 191
  • 1
  • 6
0

Delete all of the network_mode: settings. Compose will use the default network_mode: bridge. You'll be able to communicate between containers using their Compose service names as host names, as described in Networking in Compose in the Docker documentation.

version: "3.8"
services:
  akira:
    build: .
    env_file: .env
    environment:
      PGHOST: database

  database:
    image: postgres:latest
    ...

In SO questions I frequently see trying to use network_mode: to make other things appear as localhost. That host name is incredibly context-sensitive; if you asked my laptop, one of the Stack Overflow HTTP servers, your application container, or your database container who localhost is, they'd each independently say "well I am of course" but referring to a different network context. network_mode: service:... sounds like you're trying to make the other container be localhost; in practice it's extremely unusual to use this.

You may need to change your application code to make settings like the database location configurable, depending on where they're running, and environment variables are an easy way to set this in Docker. For this particular example I've used the $PGHOST variable the standard PostgreSQL client libraries use; in a Typescript/Node context you may need to change your code to refer to process.env.SOME_HOSTNAME instead of 'localhost'.

David Maze
  • 130,717
  • 29
  • 175
  • 215
  • Thanks but when I use this solution I cannot access the database outside of Docker, tried to connect to both localhost and database as host, I do have `"forwardPorts": [5432],` of course –  Nov 17 '21 at 12:33
  • If you add `ports:` to the database container, you'll be able to access it from outside of Docker too. Note that the host name will be different from inside Docker (`database`) vs. outside (`localhost`). – David Maze Nov 17 '21 at 12:43
  • I was not able to get that to work, I added `- 5432:5432`, then from outside I tried to connect using localhost as host –  Nov 17 '21 at 12:55
  • I have edited the question with my latest files, could you check if it works for you? Even after a rebuild without cache I'm not able to access the database on my host machine, maybe it's worth mentioning I'm using wsl –  Nov 17 '21 at 17:43
0

If you're using Docker on WSL, I found that I can often not connect when the process is listening on ::1, but when explicitly binding the port to 127.0.0.1 makes the service accessible through Windows.

So something like

ports:
  - 127.0.0.1:5432:5432

might work

DarkSeraphim
  • 121
  • 4