Connect to a database on the host in a Docker container from a virtual machine

Docker is an emerging technology to launch applications without installation. The same host can run multiple Docker containers of any type, so one physical or virtual server can serve as a complete mini cloud environment. Most of the time Linux is used as the host operating system.

In this example, we will launch a PostgreSQL Docker container on macOS, and access the PostgreSQL database server from a Windows VirtualBox virtual machine.

From VMware Fusion

  1. Configure the first network adapter to use NAT

From Virtual Box

Create a network between the guest VM and the host in Oracle VirtualBox

A VirtualBox virtual machine can share the networking with the host with the NAT setting, or it can be an independent computer on the network with the Bridged setting.

To access the host directly from the guest VM we can set up a host-only network, that only the host and the guest can access. This way we can launch a container on the host and access it from the guest via the host-only mini-network.

To set up the private host-only network

  1. Open the VirtualBox application and shut down all virtual machines
  2. In the File menu select Host Network Manager
  3. On the Host Network Manager window click the Create button
  4. Click the Enable checkbox in the DHCP Server column and click the Close button

Connect the virtual machine to the host-only network

The VirtualBox virtual machines can have four virtual network adapters. Always use the first adapter to connect to the host-only network.

  1. Select the virtual machine in the list and click the Settings icon
  2. On the Network tab click the arrow next to the Attached to drop-down
  3. Select the Host-only adapter
  4. The host-only network is automatically selected
  5. Select the second adapter, click the Enable Network Adapter checkbox, and select NAT
  6. Click the OK button to close the window.

Find the IP address of the host machine

When using VMware Fusion

WMware Fusion registers a local IP address to access the Mac host from the guest machine. On the Mac host terminal execute

ifconfig vmnet8

vmnet8: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
ether 00:50:56:c0:00:08
inet 192.168.2.1 netmask 0xffffff00 broadcast 192.168.2.255

Add the IP address to the C:\Windows\System32\drivers\etc\hosts file

192.168.2.1 mac.localhost

In your connection string use the address mac.localhost as the database URL

When using Oracle Virtual Box

On Docker version 18.03 and above you can use host.docker.internal to connect to the host machine.
On older Docker versions

  1. Open a terminal on the host machine.
  2. On Mac
    1. enter the following command. Use the IP address range of the host-only network above.
      ifconfig | grep 192.168

      inet 192.168.56.1 netmask 0xffffff00 broadcast 192.168.56.255

    2. Based on the output  above, the IP address of the host machine is 192.168.56.1

Launch a PostgreSQL Docker container

  1. Create a docker-compose.yml file. Containers are ephemeral, when we terminate them, all data stored inside the container is lost. We want to keep the database files on our local hard drive, so this configuration will map the /var/lib/postgresql/data directory of the Docker container to the pgdata subdirectory of the current working directory. The 5432 is the default port of the PostgreSQL database server, we will expose it on port 5432 of the host with
    version: '3'
    
    services:
      postgres:
        image: postgres:10
        env_file: .env
        ports:
          - "5432:5432"
        restart: always
        volumes:
          - $PWD/pgdata:/var/lib/postgresql/data
  2. Open a terminal window in the same directory and launch the Docker container
    docker-compose up -d

Connect to the host machine from the guest machine

Test the connection

  1. Open a terminal on the guest machine
  2. Test the connection to the host machine
    
    
    ping host.docker.internal

    or

    ping 192.168.56.1

Configure your application on the virtual machine to connect to the Docker PostgreSQL database server on the host

  1. Change the connection string, and specify the exposed port on the host machine:
    "Server=host.docker.internal;Port=5432;Database=MY_DATABASE;Username=MY_USERNAME;Password=MY_PASSWORD"

    or

    "Server=192.168.56.1;Port=5432;Database=MY_DATABASE;Username=MY_USERNAME;Password=MY_PASSWORD"

Join the Conversation

2 Comments

    1. Hello Daevid,

      Thank you for finding the typo. We expose the database on the standard port 5432 in the script. An earlier version of the script used port 5433, because I also had another PostgreSQL instance running on my machine.

Leave a comment

Leave a Reply