Skip to content

Conversation

cprecioso
Copy link
Member

@cprecioso cprecioso commented Sep 22, 2025

Adds an optional --db-image argument to the wasp start db command, allowing users to specify a custom Docker image for their development database.

This is part of #3174. We're adding ask-the-documents to the repo, which needs a specific PostgreSQL extension. This way we can more easily test the app locally.

Changes

  • Added --db-image argument parsing
  • Modified wasp start db to accept and use custom Docker images
  • Added documentation highlighting the extensions use case

Usage

# Use default PostgreSQL image (uses `postgres`)
wasp start db

# Use specific PostgreSQL version
wasp start db --db-image postgres:15

# Use PostgreSQL with PostGIS extension
wasp start db --db-image postgis/postgis:14-3.2

# Use PostgreSQL with pgvector extension
wasp start db --db-image pgvector/pgvector:pg16

Note

🤖 Generated with Claude Code
and 👨🏻 reviewed and edited by a person

Allows users to specify a custom Docker image when starting the development database.
Usage: wasp start db --image postgres:15

This enables developers to test with different PostgreSQL versions or custom database images.
- Note default postgres image in help text
- Add error handling for unrecognized arguments
- Use fromMaybe to simplify image selection logic
- Add comprehensive documentation in CLI and database docs
- Replace manual argument parsing with Options.Applicative parser
- Move parser to top level as requested
- Add note about PostgreSQL extensions use case in documentation
- Remove redundant CLI documentation as requested
- Change StartDbArgs from newtype to data type
- Move startDbArgsParser below the main start function
- Parse arguments as the first operation in start function
Copy link

cloudflare-workers-and-pages bot commented Sep 22, 2025

Deploying wasp-docs-on-main with  Cloudflare Pages  Cloudflare Pages

Latest commit: 658f0dc
Status: ✅  Deploy successful!
Preview URL: https://059fd91c.wasp-docs-on-main.pages.dev
Branch Preview URL: https://db-image-arg.wasp-docs-on-main.pages.dev

View logs

@cprecioso cprecioso marked this pull request as ready for review September 22, 2025 13:50
@cprecioso cprecioso requested a review from Martinsos September 22, 2025 13:51
@cprecioso
Copy link
Member Author

Tested with PostGIS and pgvector images, both work fine!

@cprecioso cprecioso changed the title Add --image argument to wasp start db command Add --image argument to wasp start db command Sep 22, 2025
Copy link
Contributor

@sodic sodic left a comment

Choose a reason for hiding this comment

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

I like the feature.

I want to request one main change: We should refactor the system in a way that the default case is just an instantiation of a particular image, not a special procedure.

In other words, we want wasp start db to mean (as closely as possible) wasp start db --image postgres, both in terms of how we implement it and how we communicate it with users. There are a few comments talking about what this means for different parts of our code.

Other than that, I found some small stuff: missing help text, function name, etc.

Comment on lines 5 to 7
### 🔧 Small improvements

- You can now specify which PostgreSQL image to use in `wasp start db` with the `--image` argument. ([#3182](https://github.com/wasp-lang/wasp/pull/3182))
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd list this as a new feature, not a small improvement.

It may not be useful to everybody but it is a feature :)

title " IN PROJECT",
cmd " start Runs Wasp app in development mode, watching for file changes.",
cmd " start db Starts managed development database for you.",
cmd " start db [--image <image>]",
Copy link
Contributor

Choose a reason for hiding this comment

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

We're missing this help text when we run wasp db. Plus, we could include some examples for wasp start:

image

Copy link
Member Author

Choose a reason for hiding this comment

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

Include some examples for wasp start in wasp db?

You can also specify a custom Docker image to use for the database with the `--image` option. This is particularly useful when you need PostgreSQL with specific extensions (like PostGIS for geographic data, pgvector for embeddings, etc.):

```bash
# Use default PostgreSQL image
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should say what the default is, maybe even communicate it as:

wasp start db is a shorthand for wasp start db -- image postgres

Comment on lines +45 to +48
start args = do
startDbArgs <-
parseArguments "wasp start db" startDbArgsParser args
& either (E.throwError . CommandError "Invalid arguments") return
Copy link
Contributor

Choose a reason for hiding this comment

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

No need to change anything here, just FYI.

I rarely use & in Haskell. I believe it's more idiomatic doing stuff from right to left (which is unfortunate) so I'm not used to seeing this.

Here's how I would probably write this:

start args = do
  startDbArgs <-
    either (E.throwError . CommandError "Invalid arguments") return $
      parseArguments "wasp start db" startDbArgsParser args

Or even like this:

start args = do
  startDbArgs <- case parseArguments "wasp start db" startDbArgsParser args of
    Left err -> E.throwError $ CommandError "Invalid arguments" err
    Right parsedArgs -> return parsedArgs

You can pick whatever you like the most, all options are perfectly valid.

Copy link
Member

Choose a reason for hiding this comment

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

Opposite opinion: I think the current code with the & is the best one.

While & is not that popular as $, I don't see any reason why one would not use it in appropriate places("appropriate" being the key here).

In Haskell, you anyway read both from left to right and right to left, it depends on the situation, so there is no golden rule here.

It does make sense to stick with how people normally write Haskell, so I agree one shoudln't go crazy with &, but here I think its usage is perfect, because it allows you to read code in the right order -> business logic is in focus, error handling comes after (and is even nicely indented). So I can read it as do this, but if error this and I think that is perfect.

Copy link
Member Author

Choose a reason for hiding this comment

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

In this case it's written like that for consistency, like in here:

createNewProject :: Arguments -> Command ()
createNewProject args = do
newProjectArgs <-
parseArguments "wasp new" newProjectArgsParser args
& either Common.throwProjectCreationError return

I think a good idea in general for this would be to start using Options.Applicative for all of our CLI argument parsing, not just occasionally.

Comment on lines 123 to 133
++ ( if isJust customImage
then [" ℹ Using custom Docker image: " <> dockerImage, ""]
else []
)
++ [ "Additional info:",
" ℹ Connection URL, in case you might want to connect with external tools:",
" " <> connectionUrl,
" ℹ Database data is persisted in a docker volume with the following name"
<> " (useful to know if you will want to delete it at some point):",
" " <> dockerVolumeName
]
Copy link
Contributor

Choose a reason for hiding this comment

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

At this point (and perhaps even at an earlier one), I think it makes sense to extract these messages into their own variables inside the where block. There's a lot of nesting.

@cprecioso What do you think?

Copy link
Member Author

Choose a reason for hiding this comment

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

Actually the nesting was basically unnecessary, now it's all in the top level. I don't really like extracting it somewhere else, and now it's simpler, so I think I'll leave it as-is.

"To run PostgreSQL dev database, Wasp needs `docker` installed and in PATH."
throwIfDevDbPortIsAlreadyInUse

let dockerImage = fromMaybe "postgres" customImage
Copy link
Contributor

@sodic sodic Sep 24, 2025

Choose a reason for hiding this comment

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

I believe we should do this part outside of the calling function and send the final image in as an argument:

startPostgresDevDb :: Path' Abs (Dir WaspProjectDir) -> String -> String -> Command ()
startPostgresDevDb waspProjectDir appName image = do

There isn't really a reason for this function to take in an optional and then
Also, I see the name was changed from "postgres" to "postgre." I believe this is incorrect: the official name of the project is "PostgreSQL" and its nickname is "Postgres." (wikipedia).

Copy link
Member Author

Choose a reason for hiding this comment

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

Huh weird thing about the Postgres thing, I didn't realize!

Comment on lines 123 to 125
++ ( if isJust customImage
then [" ℹ Using custom Docker image: " <> dockerImage, ""]
else []
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think we need any special text here. We should always say "Using Docker image ...."

The default case should just be a default value for something, not a special procedure. This means:

  • We set the default value at the top of the "system."
  • Everything else is completely agnostic on whether it's working with the default value or the custom value.

Comment on lines 35 to 38
-- | Command-line arguments for `wasp start db`
data StartDbArgs = StartDbArgs
{ customDbImage :: Maybe String
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Since we have all this parsing logic in the same file, I suggest moving this datatype below start.

Our rule is:

  1. Exported stuff before private stuff
  2. If A is used in B, A should come as soon as possible after B without breaking the first rule (I think Clean Code has a nice name for this rule, can't remember now)

Unfortunately, many files don't stick to this rule since we can't automate it (at least I think we can't) and sometimes forget. But when we remember, we should follow it :)

Copy link
Member

Choose a reason for hiding this comment

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

Do we have super strict rule for this? If we do I have to admit I forgot it.
My rule is, make it read like a story (Clean Code also). Almost always that will match what you wrote above, but there could be some exceptions.

Copy link
Member

@Martinsos Martinsos left a comment

Choose a reason for hiding this comment

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

Nice stuff! Some good comments were already left by others, but I also left some of my own.

One thing I am wondering about is the workflow itself -> let's say somebody is using custom dev db, do they have to keep passing this arg all the time? Is that a bit cumbersome? I guess they will have to set up some kind of small shell script to serve as a runner so they don't have to repeat it.

I commented in Railway (or was it Fly) PR also on this. I wonder if it would make sense, from the DX perspective, to actually also have a central place to define a default database image, that would be used both in dev and when deploying. Since at the end, it is a property of the full stack app -> when you are building your wasp app, you are assuming some kind of database, and ideally you would use the same exact database setup both in dev and in prod. I am sure that might not always be so, but it would be nice if this primary use case is supported by us.

This doesn't have to be done in this issue, but I would like us to think/discuss about it, now that we are doing this.

Comment on lines 35 to 38
-- | Command-line arguments for `wasp start db`
data StartDbArgs = StartDbArgs
{ customDbImage :: Maybe String
}
Copy link
Member

Choose a reason for hiding this comment

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

Do we have super strict rule for this? If we do I have to admit I forgot it.
My rule is, make it read like a story (Clean Code also). Almost always that will match what you wrote above, but there could be some exceptions.

Comment on lines +45 to +48
start args = do
startDbArgs <-
parseArguments "wasp start db" startDbArgsParser args
& either (E.throwError . CommandError "Invalid arguments") return
Copy link
Member

Choose a reason for hiding this comment

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

Opposite opinion: I think the current code with the & is the best one.

While & is not that popular as $, I don't see any reason why one would not use it in appropriate places("appropriate" being the key here).

In Haskell, you anyway read both from left to right and right to left, it depends on the situation, so there is no golden rule here.

It does make sense to stick with how people normally write Haskell, so I agree one shoudln't go crazy with &, but here I think its usage is perfect, because it allows you to read code in the right order -> business logic is in focus, error handling comes after (and is even nicely indented). So I can read it as do this, but if error this and I think that is perfect.

@cprecioso
Copy link
Member Author

@Martinsos

I wonder if it would make sense, from the DX perspective, to actually also have a central place to define a default database image

Yes, I agree. This also makes me feel like what @infomiho once said about having a deployment config file might also make sense. As you said, I think it might be out-of-scope for this PR, but we could start looking into it. (If/when we conclude that custom DB images are a feature that people do use)

@cprecioso
Copy link
Member Author

@sodic @Martinsos ready

@Martinsos
Copy link
Member

Martinsos commented Sep 25, 2025

@Martinsos

I wonder if it would make sense, from the DX perspective, to actually also have a central place to define a default database image

Yes, I agree. This also makes me feel like what @infomiho once said about having a deployment config file might also make sense. As you said, I think it might be out-of-scope for this PR, but we could start looking into it. (If/when we conclude that custom DB images are a feature that people do use)

I do think they are needed for sure, the custom DB images. But sure more data will be helpful.

There is one older related issue: #169 . And I know Miho did some work on it in the meantime where i also aprticipated but can't find it right now, I asked him to link it there.

EDIT: I also created issue for it here: #3193 .

Copy link
Member

@Martinsos Martinsos left a comment

Choose a reason for hiding this comment

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

Couple of comments, but once you resolve them, I am good with merging!

" supplied migration name or asking for one.",
" start [--db-image <image>] Alias for `wasp start db`.",
" Starts managed development database for you.",
" Optionally specify a custom Docker image."
Copy link
Member

Choose a reason for hiding this comment

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

Not the same as for wasp start db (missing "with --db-image). I would add it here or remove it up there.

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't get this comment, can you clarify? I do handle the argument in both cases.

Copy link
Member

Choose a reason for hiding this comment

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

Aha sorry, I should have been more verbose! So CLI docs for wasp start db are very similar, but a bit different, and there is no reason for them to be different, so I was suggesting to make them the same. THe difference is in "with --db-image" part).

Copy link
Member Author

Choose a reason for hiding this comment

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

ahh understood, my eyes were skipping over that haha

@cprecioso cprecioso changed the title Add --image argument to wasp start db command Add --db-image argument to wasp start db command Sep 26, 2025
@cprecioso cprecioso merged commit a8ffba4 into main Sep 26, 2025
7 checks passed
@cprecioso cprecioso deleted the db-image-arg branch September 26, 2025 09:29
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.

Enable specifying custom Docker image for managed dev database wasp db start
3 participants