Notes on working with Hasura & Postgres docker containers in a local mac environment.
Table of content:
Download the hasura docker-compose file (docker-compose.yml
). From Hasura's QuickStart with Docker Guide:
# in a new directory run
wget https://raw.githubusercontent.com/hasura/graphql-engine/stable/install-manifests/docker-compose/docker-compose.yaml
# or run
curl https://raw.githubusercontent.com/hasura/graphql-engine/stable/install-manifests/docker-compose/docker-compose.yaml -o docker-compose.yml
Before running the containers, add the following to the yaml file:
postgres:
# (optional) add the following to expose the database endpoint if you want to access it locally (e.g. for SchemaSpy):
# 5432 is the default port of postgres container
ports:
- "5432:5432"
graphql-engine:
environment:
# to avoid some error that may appear where the console gets stuck at 'loading ...' -- see reference [1]
HASURA_GRAPHQL_CONSOLE_ASSETS_DIR: /srv/console-assets
to run the containers together, use the following command in the same directory where the `docker-compose.yml` is:
[~]$ docker-compose up -d
Now the containers are running. Reruning the command above again (after the containers has stopped) will run the same containers. The containers will not be recreated unless the yaml
file has changes. Even then only the container with changes will be recreated. It's worth noting that the compose file mounts the data to a volume called db_data
which is part of Docker (see Mounting Postgre volume locally below if you prefer to have the volume outside of Docker).
To stop the containers, you first need to get the containers ids:
# to see the running containers
[~]$ docker ps
# to stop the containers
[~] docker stop <container_id>
# to stop multiple containers
[~] docker stop <container_id> <container_id>
# to stop all runing containers (-q = --quiet that prints containter-ids only)
[~]$ docker stop $(docker ps -q)
to stop the containers + remove them + remove the networks, volumes, and images that were created by docker-compose, run the following command:
# warning: this will delete the volumes
[~] docker-compose down
Other useful commands for viewing the logs
# view the logs
[~]$ docker logs <container_id>
# to redirect the logs to a file
# no need to append (i.e, >> ) since the command export the entire log anyway
[~]$ docker logs <container_id> > <file_name>.log
# to keep the log running in the terminal (-f = --follow)
[~]$ docker logs -f <container_id>
# to redirect the logs to a file as they are come
# postgres containger won't redirect to file when with `follow` for some reason
[~]$ docker logs -f <container_id> > output.log
If you like the to mount the database volume outside the container (local directory), here's an example of how it can be done:
## under postgres container, add the following:
postgres:
image: postgres:12
volumes:
- db_data:/var/lib/postgresql/data
Then, add the following at volumes:
volumes:
db_data:
driver: local
driver_opts:
type: 'none'
o: 'bind'
device: '~/User/Projects/hasura_project/db_data' # example path in MacOS
Note: there could be an issue with mounting the volume locally as this warning will appear in the logs of postgres container:
WARNING: could not open statistics file "pg_stat_tmp/global.stat": Operation not permitted
Here's a good explaination to what
global.stat
is: https://stackoverflow.com/a/32193782/10976714I still haven't figured out how a fix as it's not causing an issue for local development (if you see this and know how to fix, please comment below).
(update: I believe after Hasura 2.0, this is done automatically tho I will leave it here for reference)
When adding a top level function (to root query), and you need to access the hasura-session
, add the following configuration in order for the query to work:
"functions": [
{
"function": {
"schema": "public",
"name": "get_session_role" // see example below
},
"configuration": {
"session_argument": "hasura_session" // see details below
}
},
],
example: Example function
details : details about configruation
[1] github issue: Generic error when modifying database schema
[2] how to redirect docker logs to a single file
1- enter the postgres container terminal
[~] docker exec -it <container_id> bin/bash
# note: hasura container doesn't have bash, so you need to use shell instead
[~] docker exec -it <hasura_container_id> sh
2- To enter the postgres interactive terminal (i.e., psql
):
first we need to log in. The username and password are inside the docker-compose.yml
file (i.e., postgres
& postgrespassword
respectively).
# the username and password are inside the docker-compose.yml
# default: username=postgres & password=postgrespassword
root@<container_id>: psql -U username -W
# you'll be promted to enter the password
password: ******
# now you'll be inside the postgres interactive terminal
postgres$
3 - interact with the terminal and here's a list of useful commands:
# most commands starts with "\"
# for help menu:
postgres$ \?
# list database
postgres$ \l
# list tables
postgres$ \dt
# to query
postgres$ SELECT * FROM table_name LIMIT 1;
# list a specific table (e.g. `users` table)
postgres$ \d users
# to exit
postgres$ \q # or simply `exit`
# to exit the container
root@<container_id>: exit
- using
psql
terminal
# to turn on/off expanding display
postgres$ \x
# find the name of the function
postgres$ \df
# find the name of the function/trigger based on a schema
postgres$ \df public.*
# print the function definition (the plus sign will print extra information like the source code)
postgres$ \df+ name_of_function
- using
sql
select proname,prosrc from pg_proc where proname= your_function_name;
Explain only:
EXPLAIN SELECT count(*) FROM pg_attribute;
output:
Aggregate (cost=119.66..119.67 rows=1 width=8)
-> Seq Scan on pg_attribute (cost=0.00..110.13 rows=3813 width=0)
Explain and Analyze query
EXPLAIN (ANALYZE, buffers, timing) SELECT count(*) FROM pg_attribute;
output:
Aggregate (cost=119.66..119.67 rows=1 width=8) (actual time=31.324..31.339 rows=1 loops=1)
Buffers: shared hit=72
-> Seq Scan on pg_attribute (cost=0.00..110.13 rows=3813 width=0) (actual time=0.008..15.608 rows=3813 loops=1)
Buffers: shared hit=72
Planning Time: 0.129 ms
Execution Time: 31.387 ms
Further reading:
- Back to basics
psql
: https://thoughtbot.com/blog/psql-basics - PostgreSQL tutorial website: https://www.postgresqltutorial.com/
- PostgreSQL offical tutorial: https://www.postgresql.org/docs/12/tutorial.html
Inside the postgres container, there's a client application called: pg_dump that can be used to dump the schema or the data.
# to dump the database:
# don't run this command (see below to dump on a file)
[~]$ docker exec <container_id> pg_dump --dbname=<database_name> --username=<user_name>
# for example
[~]$ docker exec 233a263da1fc pg_dump --dbname=postgres --username=postgres
# for some reason the password isn't required
# to export schema only to a file
[~]$ docker exec <container_id> pg_dump -s -d postgres -U postgres > pg_dump_schema_only.psql
# to export a specific schema and its data to a file
[~]$ docker exec <container_id> pg_dump --schema=public -d postgres -U postgres > pg_dump_public_schema_and_data.psql
# to export a specific schema only (-s means schema only and -n schema name)
[~]$ docker exec <container_id> pg_dump -s -n public -d postgres -U postgres > pg_dump_public_schema_only.psql
# for more options run
[~]$ docker exec <container_id> pg_dump --help
Here are other: PostgreSQL Client Applications
SchemaSpy generates the database to HTML documentation, including Entity Relationship diagrams.
- Their container:
schemaspy/schemaspy:latest
- github: https://github.com/schemaspy/schemaspy
- website: http://schemaspy.org
- sample output: http://schemaspy.org/sample/relationships.html
1- create a config file called config/schemaspy.properties
and add the following:
# note: make sure there is no spaces after properties
# `localhost` or `127.0.0.1` doesn't work on mac, use `host.docker.internal`
schemaspy.t=pgsql
schemaspy.host=host.docker.internal
schemaspy.port=5432
schemaspy.db=postgres
schemaspy.u=postgres
schemaspy.p=postgrespassword
schemaspy.schemas=public
2- to generate SchemaSpy html file, run the following:
docker will get the container for you if you don't have it
[~]$ docker run -v $PWD/output:/output -v $PWD/config/:/config/ schemaspy/schemaspy:latest -configFile /config/schemaspy.properties
# $PWD/output is where the output will be on the your machine
3- open the index.html
file inside $PWD/output
to view the SchemaSpy
get-graphql-schema is an npm package to get the graphql schema from a graphql endpoint. For hasura, the endpoint is shown on the the graphql tab. When running as a local host, the url is http://localhost:8080/v1/graphql
:
# install the package with npm:
[~]$ npm install -g get-graphql-schema
# example: generate the schema to a file
[~]$ get-graphql-schema http://localhost:8080/v1/graphql > hasura_graphql_schema.graphql
# if the endpoints are secured, you need to include the admin secret (-h = --header):
[~]$ get-graphql-schema -h 'x-hasura-admin-secret=adminsecret' http://localhost:8080/v1/graphql > hasura_graphql_schema_alllow_list_enabled.graphql
If you like to get the schema for a specific role (e.g. user
), it can be done as follow by using multiple headers:
get-graphql-schema -h 'x-hasura-admin-secret=adminsecret' -h 'x-hasura-role=user' http://localhost:8080/v1/graphql > hasura/hasura_graphql_schema_for_user_role.graphql
This is a very useful article about GraphQL introspection:
an example:
GraphQL | Output |
---|---|
{
__schema {
queryType {
name
}
}
} |
{
"data": {
"__schema": {
"queryType": {
"name": "Query"
}
}
}
} |
This is useful in Hasura when you like to extract the schema for a specific authenticated type (user, anonymous). By setting the x-hasura-role
in the header, the result will only include the schema where the user has permission. Unlike, downloading the entire schema, this can download a user-specific schema.
See this:
PostgreSQL - run queries and view table from VS code!
[PostgreSQL extention] is a query tool for PostgreSQL databases. While there is a database explorer it is NOT meant for creating/dropping databases or tables. The explorer is a visual aid for helping to craft your queries.
link: https://marketplace.visualstudio.com/items?itemName=ckolkman.vscode-postgres
GraphQL - useful for formatting and highlighting .graphql
extension.
GraphQL extension for VSCode adds syntax highlighting, validation, and language features like go to definition, hover information and autocompletion for graphql projects. This extension also works with queries annotated with gql tag.
link: https://marketplace.visualstudio.com/items?itemName=GraphQL.vscode-graphql
pgFormatter helpful for formatting query files (.pgsql
, .psql
, and other extentions).
A VS Code extension that formats PostgreSQL SQL, using the Perl based pgFormatter tool developed by Gilles Darold.
link: https://marketplace.visualstudio.com/items?itemName=bradymholt.pgformatter
The best reference for PostgreSQL is their documentation. Note that Hasura, at the time of writing this, uses PostgreSQL version 12.
For Hasura & GraphQL, the best referene their documentation & their learn section.
Youtube Channels:
- Hasura GraphQL 101 from Creative Bracket (beginner)
- PostgreSQL playlist from Hussein Nasser (advanced)
This gist was uploaded and updated with ease using: https://github.com/defunkt/gist