Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(cli): Use an IPV6-enabled network in CLI's compose file #1299

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

alco
Copy link
Member

@alco alco commented May 24, 2024

This PR changes two things:

  1. Removes one of the compose files, reducing duplication. Now we can no longer get into a situation where the sync service definition is updated in one file but not in the other one.
  2. Adds an IPv6-enabled network definition to the compose file and makes the electric service use that network.

Background

Beyond requiring support in the OS, the network router and the ISP, there are two more problems with using IPv6 for database connections:

  • it's not automatically enabled in Docker
  • an explicit network configuration needs to be added to the compose file when the sync service is started by docker compose

The first problem is relevant to those users who utilize docker run to start the sync service. The second problem currently makes our CLI unusable with IPv6 because the compose file bundled with it has no provisions for IPv6 networking. This PR address the latter.

Testing

I have tested connectivity from the sync service to a Supabase database over IPv6 and to a DigitalOcean Managed PostgreSQL over IPv4. Here's what I've learned:

  • Once IPv6 support has been enabled in the Docker daemon, it seems to persist even after the configuration file is removed and the daemon is restarted. For example, with IPv6 disabled in the Docker daemon (such that docker run ... curlimages/curl -6 https://ifconfig.co/ip fails to connect to the remote host) it is still possible to define an IPv6-enabled network in a compose file and the services started by docker compose will be able to connect to remote hosts over IPv6.
  • The compose file may include a minimalistic network definition that only includes the enabled_ipv6: true line. But for this to work, the Docker daemon must be configured with an IPv6 default pool. Otherwise, the network definition in the compose file has to include a subnet definition.
  • Alternatively, the network definition in the compose file may be marked with external: true to instruct docker compose to use a user-created Docker network instead of creating a new one.
  • The CIDR prefix configured in Docker daemon's default pool(s) and the subnet in the compose file do not need to match.
  • An IPv6-enabled network also supports IPv4 connectivity.

In summary, including a default IPv6-enabled network definition in our packaged compose file should work regardless of how users have their Docker daemon configured.

There is a potential for conflict, though. If there's already a Docker network on the machine that has an overlapping subnet with the one we define in our compose file, docker compose up will fail. To minimize the chances of conflicts, I have chosen a subnet with randomly generated groups that has the size of only 4 address. To make it fully conflict-proof, the compose file has three environment variables that can be used to either redefine the subnet or instruct docker compose to use a different, user-created Docker network by name.

Fixes #863.

@alco alco marked this pull request as ready for review May 24, 2024 22:26
@alco alco changed the title fix(cli): Use an IPV6-enable network in CLI's compose file fix(cli): Use an IPV6-enabled network in CLI's compose file May 24, 2024
@alco alco force-pushed the alco/cli-compose branch 2 times, most recently from 4663b68 to ef6a1c7 Compare May 27, 2024 07:47
Copy link
Contributor

@msfstef msfstef left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, and nice work with reducing the config to a single file, much easier to maintain!

I've left a comment with regard to configuring the network, as my opinion is that we should aim to make it work by default as much as possible and offload any additional requirements to the user via a guide on setting up a custom docker compose, e.g. by adding a CLI command electric-sql eject that copies the docker compose file to the dev's project for them to configure any way they want.

msfstef added a commit that referenced this pull request Jun 5, 2024
Redacts any value marked as confidential in the configuration options
from the config.

I've also removed the version from the docker compose files as it is
deprecated and shows warnings any time we use them - I'd also collapse
them in one as @alco did but it can wait until
#1299 is merged
@alco alco force-pushed the alco/cli-compose branch 2 times, most recently from e1f75a5 to 4b54948 Compare June 22, 2024 22:11
@alco
Copy link
Member Author

alco commented Jun 26, 2024

I've tested the updated implementation in the following scenarios by running a starter app on an Ubuntu DO droplet and installing the development version of the CLI as an npm pack:

  • ✅ connect to Supabase using host networking by setting ELECTRIC_DOCKER_NETWORK_USE_EXTERNAL=host
  • ✅ connect to Supabase using a Compose-created network (default behaviour of npx electric-sql start)
  • ✅ create a standalone Docker network with docker network create --ipv6 --subnet 2001:db8::/64 ip6net and connect to Supabase using the setting ELECTRIC_DOCKER_NETWORK_USE_EXTERNAL=ip6net
  • ✅ connect to a Crunchybridge database over IPv4, with DATABASE_USE_IPV6 set to either true or false

@alco alco requested a review from msfstef June 27, 2024 06:50
Copy link
Contributor

@msfstef msfstef left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! Looks good and love the new way of configuring the network!

Testing it I seem to be having issues with flags and defaults - the --with-postgres flag doesn't seem to be working at all no matter how I set it. I saw you raised a seemingly related issue #1404, are you seeing the same thing or have I perhaps messed something up in my local build? EDIT: it was a local build issue, runs fine when I make sure I'm running the right CLI build!

Also, we might want to switch the ELECTRIC_WRITE_TO_PG_MODE default to direct_writes rather than logical_replication since we're shifting to that soon (see #1342 and we've already updated examples and docs to use direct writes), cause when the --with-postgres flag was not detected the error I got was the LOGICAL_PUBLISHER_HOST not being set which can be confusing (as opposed to the "check your DATABASE_URL" error in direct_writes mode) - feel free to ignore this for this PR though

)
}

function useExternalDockerNetwork(opt: string): string {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we can use a more descriptive/strict type signature and argument

function useExternalDockerNetwork(networkName?: string) : 'true' | 'false' {
    return (networkName && networkName.length > 0) ? 'true' : 'false'
}

or even return a boolean and let the calling function cast it to an appropriate string (?) I'd avoid the toString call cause its behaviour never feels obvious to me

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But returning a boolean here means using toString() later to cast it. I'm not sure what is not obvious about the behaviour of toString.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mostly that in JS I'm never sure what the toString implementation will result in (e.g. 't' and 'f') and if we specifically need 'true' or 'false' strings having a flag ? 'true' : 'false' feels more explicit. Granted for the boolean case it's fairly standard so feel free to ignore me, I just always start from a "don't trust JS to have standard behaviour" standpoint :P

components/cli/src/docker-commands/docker-utils.ts Outdated Show resolved Hide resolved
@alco
Copy link
Member Author

alco commented Jun 27, 2024

Also, we might want to switch the ELECTRIC_WRITE_TO_PG_MODE default to direct_writes rather than logical_replication since we're shifting to that soon (see #1342 and we've already updated examples and docs to use direct writes), cause when the --with-postgres flag was not detected the error I got was the LOGICAL_PUBLISHER_HOST not being set which can be confusing (as opposed to the "check your DATABASE_URL" error in direct_writes mode) - feel free to ignore this for this PR though

This needs to be addressed separately.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

electric-sql generate stuck while using Supabase
2 participants