{"id":26415203,"url":"https://github.com/mugilan-codes/objection-knex-demo","last_synced_at":"2026-04-09T01:31:20.864Z","repository":{"id":105886151,"uuid":"371133318","full_name":"Mugilan-Codes/objection-knex-demo","owner":"Mugilan-Codes","description":"Objection Knex Node Express App with Docker Deployment to AWS AMI Linux instance practice","archived":false,"fork":false,"pushed_at":"2021-06-10T09:14:38.000Z","size":720,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-03T16:32:14.492Z","etag":null,"topics":["aws","aws-ec2","docker","docker-compose","dockerfile","express","knex","knexjs","mysql","nodejs","objection-orm","objectionjs","wait-for"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Mugilan-Codes.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-05-26T18:29:52.000Z","updated_at":"2023-03-09T02:09:55.000Z","dependencies_parsed_at":"2023-04-13T04:23:52.228Z","dependency_job_id":null,"html_url":"https://github.com/Mugilan-Codes/objection-knex-demo","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Mugilan-Codes/objection-knex-demo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mugilan-Codes%2Fobjection-knex-demo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mugilan-Codes%2Fobjection-knex-demo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mugilan-Codes%2Fobjection-knex-demo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mugilan-Codes%2Fobjection-knex-demo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Mugilan-Codes","download_url":"https://codeload.github.com/Mugilan-Codes/objection-knex-demo/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mugilan-Codes%2Fobjection-knex-demo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31581864,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-08T14:31:17.711Z","status":"ssl_error","status_checked_at":"2026-04-08T14:31:17.202Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","aws-ec2","docker","docker-compose","dockerfile","express","knex","knexjs","mysql","nodejs","objection-orm","objectionjs","wait-for"],"created_at":"2025-03-18T00:17:51.052Z","updated_at":"2026-04-09T01:31:20.854Z","avatar_url":"https://github.com/Mugilan-Codes.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Objection ORM using Knex on MySql\n\n## Practice setup for objection knex with docker\n\n### TODO\n\n- Remove babel and use `.mjs` file extension instead of `.js`\n- Add classes support ([@babel/plugin-transform-classes](https://babeljs.io/docs/en/babel-plugin-transform-classes))\n- Add Versioning Support for API's\n- add Port 80(http) and Port 443(https) support using nginx\n- REVIEW: do wee need wait-for.sh in production?\n\n### Source\n\n- [Objection.js](https://vincit.github.io/objection.js/) ORM\n- [Knex.js](http://knexjs.org/) Query Builder\n- [Node MySQL 2](https://www.npmjs.com/package/mysql2)\n- [How to Create MySQL Users Accounts and Grant Privileges](https://linuxize.com/post/how-to-create-mysql-user-accounts-and-grant-privileges/) - (without docker)\n- [How to Create MySQL User and Grant Privileges: A Beginner’s Guide](https://www.hostinger.in/tutorials/mysql/how-create-mysql-user-and-grant-permissions-command-line) - (without docker)\n- Babel Setup\n  - [Configure Babel for a Nodejs Application](https://dev.to/adebayoileri/configure-babel-for-nodejs-application-3798)\n  - [A Minimal Node.js, Express, \u0026 Babel Setup](https://dev.to/neightjones/a-minimal-node-js-express-babel-setup-27j6)\n- Docker Compose\n  - [Use Compose in production](https://docs.docker.com/compose/production/)\n  - [Share Compose configurations between files and projects](https://docs.docker.com/compose/extends/)\n- Knex Objection ORM Tutorial\n  - [Node Objection.js tutorial with knex and Postgres | Node SQL ORM](https://youtu.be/zbIl2kuP7tE) (YouTube)\n  - [objection-js-tutorial](https://github.com/productioncoder/objection-js-tutorial)\n- [Knex Setup Guide](https://gist.github.com/NigelEarle/80150ff1c50031e59b872baf0e474977)\n- knex wait for connection\n  - [pool afterCreate](https://github.com/knex/knex/issues/3447#issuecomment-672881144)\n  - [acquireConnectionTimeout](http://knexjs.org/#Installation-acquireConnectionTimeout)\n  - [Setting up Docker with Knex.js and PostgreSQL](https://stackoverflow.com/questions/48751074/setting-up-docker-with-knex-js-and-postgresql)\n  - [Docker wait for postgresql to be running](https://stackoverflow.com/a/61202718/12381908)\n  - [Waiting for MySQL to come up before talking to it](https://github.com/docker-library/mysql/issues/547#issuecomment-471093838)\n  - [bonita example](https://github.com/docker-library/docs/blob/9660a0cccb87d8db842f33bc0578d769caaf3ba9/bonita/stack.yml#L28-L44)\n  - [wait-for-it Usage with Docker #57](https://github.com/vishnubob/wait-for-it/issues/57)\n  - [Containerizing a Node.js Application for Development With Docker Compose](https://www.digitalocean.com/community/tutorials/containerizing-a-node-js-application-for-development-with-docker-compose)\n  - [Troubleshooting Knex Connection](https://medium.com/@isachenx/troubleshooting-knex-connection-d331cea007f2)\n- [ECMAScript modules (ESM) Interoperability](http://knexjs.org/#esm-interop)\n- [Deleting data from associated tables using knex.js](https://stackoverflow.com/a/53861921/12381908)\n- [Better logs for ExpressJS using Winston and Morgan with Typescript](https://dev.to/vassalloandrea/better-logs-for-expressjs-using-winston-and-morgan-with-typescript-516n)\n- [Express middleware: A complete guide](https://blog.logrocket.com/express-middleware-a-complete-guide/)\n- [Express Use gzip compression](https://expressjs.com/en/advanced/best-practice-performance.html#use-gzip-compression)\n- [AWS EC2 setup](https://youtu.be/rE8mJ1OYjmM) (YouTube)\n- [How to fix docker: Got permission denied while trying to connect to the Docker daemon socket](https://www.digitalocean.com/community/questions/how-to-fix-docker-got-permission-denied-while-trying-to-connect-to-the-docker-daemon-socket)\n- [Amazon Linux 2 - install docker \u0026 docker-compose](https://gist.github.com/npearce/6f3c7826c7499587f00957fee62f8ee9)\n\n### Pre-Requisite\n\n- Make the `wait-for.sh` script executable\n\n  ```sh\n  chmod +x wait-for.sh\n  ```\n\n- Modify Docker Compose `command` in the `node-app` service\n\n  ```txt\n  # ./wait-for.sh \u003cwait-for-service-name\u003e:\u003cport-of-the-service\u003e -- \u003ccommands-to-execute-after\u003e\n\n  command: ./wait-for.sh mysql:3306 -- npm run dev\n  ```\n\n### Knex Setup\n\n- Init\n\n  ```sh\n  knex init --cwd ./src/db\n  ```\n\n- Migrations\n\n  ```sh\n  knex --esm migrate:make --cwd ./src/db \u003cmigrations_name\u003e\n  ```\n\n- Seeds\n\n  ```sh\n  knex --esm seed:make --cwd ./src/db \u003cseed_name\u003e\n  ```\n\n- **IMPORTANT**: Login into docker and run `migrate` and `seed`\n\n### DOCKER COMMANDS\n\n- Image\n\n  - List images\n\n    ```sh\n    docker image ls\n    ```\n\n  - Remove one or more images\n\n    ```sh\n    docker image rm \u003cimage_name\u003e\n    ```\n\n- Container\n\n  - List Running\n\n    ```sh\n    docker ps\n    ```\n\n  - List All\n\n    ```sh\n    docker ps -a\n    ```\n\n  - Remove one or more containers\n\n    ```sh\n    docker image rm \u003cimage_name\u003e\n\n    # force\n    docker image rm \u003cimage_name\u003e -f\n\n    # volumes\n    docker image rm \u003cimage_name\u003e -v\n\n    # force and volume\n    docker image rm \u003cimage_name\u003e -fv\n    ```\n\n    **NOTE**:\n      1. `-f` or `--force`: Force the removal of a running container (uses SIGKILL)\n      2. `-v` or `--volumes`: Remove anonymous volumes associated with the container\n\n- Volumes\n\n  - List volumes\n\n    ```sh\n    docker volume ls\n    ```\n\n  - Remove all unused local volumes\n\n    ```sh\n    docker volume prune\n    ```\n\n- Access File System\n\n  - use `sh` or `ash` since `bash` is unavailable in alpine images\n\n    ```sh\n    docker exec -it \u003ccontainer_name\u003e ash\n\n    # as root user\n    docker exec -it --user root \u003ccontainer_name\u003e ash\n    ```\n\n    **NOTE**:\n      1. Run a command in a running container\n      2. `-i` or `--interactive`: Keep STDIN open even if not attached\n      3. `-t` or `--tty`: Allocate a pseudo-TTY\n\n  - check the set environment variables inside the docker container\n\n    ```sh\n    printenv\n    ```\n\n- Compose\n\n  - DEVELOPMENT\n\n    - up\n\n      ```sh\n      docker-compose up -d\n\n      # use this if there is any changes in Dockerfile to Build images before starting containers\n      docker-compose up -d --build\n\n      # re-build image without downing the container and re creating anonymous volumes\n      docker-compose up -d --build -V\n\n      # scale the number of instances\n      docker-compose up -d --scale node-app=2\n      ```\n\n      **NOTE**: `-d` or `--detach`: Detached mode: Run containers in the background\n\n    - down\n\n      ```sh\n      docker-compose down\n\n      # Remove containers and it's volumes (don't use it if you want db to persist)\n      docker-compose down -v\n\n      # Remove all images used by any service\n      docker-compose down --rmi all\n\n      # Remove only images that don't have a custom tag set by the `image` field\n      docker-compose down --rmi local\n      ```\n\n      **NOTE**: `-v` or `--volumes`: Remove named volumes declared in the `volumes` section of the Compose file and anonymous volumes attached to containers\n\n  - PRODUCTION\n\n    - up\n\n      ```sh\n      docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d\n\n      # rebuild images\n      docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build\n      ```\n\n    - down\n\n      ```sh\n      docker-compose -f docker-compose.yml -f docker-compose.prod.yml down -v\n      \n      # don't remove volumes\n      docker-compose -f docker-compose.yml -f docker-compose.prod.yml down\n      ```\n\n  **NOTE**: can also use `docker compose` instead of `docker-compose`\n\n- Database\n\n  - MySQL\n  \n    - Open MySQL (recommended)\n\n      ```sh\n      docker exec -it \u003cdb_container_name\u003e bash\n\n      mysql -u \u003cuser_name\u003e -p\n      # enter your password\n\n      use \u003cdb_name\u003e\n      ```\n\n    - directly login into mysql\n\n      ```sh\n      # open mysql\n      docker exec -it \u003cdb_container_name\u003e mysql -u \u003cuser_name\u003e --password=\u003cpassword\u003e\n\n      # directly open the database\n      docker exec -it \u003cdb_container_name\u003e mysql -u \u003cuser_name\u003e --password=\u003cpassword\u003e \u003cdb_name\u003e\n      ```\n\n  - redis\n\n    - open redis\n\n      ```sh\n      docker exec -it \u003credis_container_name\u003e redis-cli\n      ```\n\n    - View Session keys inside redis-cli\n\n      ```txt\n      KEYS *\n      ```\n\n    - Get Session Details by using the session id got from `KEYS *`\n\n      ```txt\n      GET \u003csession_key\u003e\n      ```\n\n- Cleaning\n\n  If you want a fresh start for everything, run `docker system prune -a` and `docker volume prune`. The first command removes any unused containers and the second removes any unused volumes. I recommend doing this fairly often since Docker likes to stash everything away causing the gigabytes to add up.\n\n### Production\n\n1. Launch an server on cloud (use digital ocean or aws). I am using AWS.\n  \n   - Add ubuntu in AWS EC2 instance (i chose `t2.small`).\n\n   - Select Free Tier\n\n   - Add security group for HTTP(80) and HTTPS(443) and SSH(22)\n  \n   - click `Review and Launch`\n\n   - Add Tags if you want `Key=Name` and `Value=App`\n  \n   - Create key file and store it in a secure location for ssh access\n  \n   - Launch Instance\n  \n   - Wait for instance status to be running and copy the `Public IP address`.\n  \n   - Go to the location of the downloaded key file and open the terminal.\n  \n   - type in the command to get access to the cloud instance of the ubuntu server. (`ubuntu`/`ec2-user` user is created by default)\n  \n      ```sh\n      ssh -i \u003ckey-file-name\u003e.\u003cextension\u003e ubuntu@\u003cpublic_ip\u003e\n\n      # if using AMI instance\n      ssh -i \u003ckey-file-name\u003e.\u003cextension\u003e ec2-user@\u003cpublic_ip\u003e\n      ```\n\n      **NOTE**: based on the file extension (.pem or .cer) we may need to giv it special permissions using `chmod 600 \u003ckey-file-name\u003e.\u003cextension\u003e`. run the above command again to get access to the ubuntu instance\n\n   - Update Ubuntu (Optional)\n\n      ```sh\n      # check updates available\n      sudo apt list --upgradable\n\n      # Update the repository index and install the updates for Kernel and installed applications\n      sudo apt update \u0026\u0026 sudo apt upgrade -y\n\n      # run this once the update is finished\n      sudo reboot\n      ```\n\n      **NOTE**: After rebooting wait for sometime and connect into the ubuntu instance using ssh\n\n1. [Add Deploy Keys](https://docs.github.com/en/developers/overview/managing-deploy-keys#deploy-keys) to get repository access inside the server (work even for private repository)\n\n   - Generate SSH key inside server\n\n      ```sh\n      cd .ssh/\n\n      ssh-keygen -t ed25519 -C \"your_email@example.com\"\n      ```\n\n   - Copy public key from `id_*.pub` and paste it into deploy keys section of the github repo.\n\n1. Install Docker in the Ubuntu Instance\n\n    - get [docker](https://get.docker.com/) engine community from the scripts\n\n      ```sh\n      curl -fsSL https://get.docker.com -o get-docker.sh\n\n      sh get-docker.sh\n      ```\n\n    - Install docker, git (when using `AMI instance`)\n\n      ```sh\n      sudo yum install -y docker git\n\n      sudo service docker start\n      sudo usermod -a -G docker ec2-user\n\n      # Make docker auto-start\n      sudo chkconfig docker on\n\n      # Reboot to verify it all loads fine on its own.\n      sudo reboot\n      ```\n\n    - get [docker-compose](https://docs.docker.com/compose/install/) from official documentation for linux\n\n      ```sh\n      # check the docs for version before using this command\n      sudo curl -L \"https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)\" -o /usr/local/bin/docker-compose\n\n      # get latest version\n      sudo curl -L https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose\n\n      sudo chmod +x /usr/local/bin/docker-compose\n      ```\n\n    - [Manage Docker as a non-root user](https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user) or [Run the Docker daemon as a non-root user (Rootless mode)](https://docs.docker.com/engine/security/rootless/)\n\n1. Create `.env` file inside server\n\n   - Open a .env file using vim  \n\n      ```sh\n      vim .env\n      ```\n\n   - Add environmental variables\n\n      ```vim\n      NODE_ENV=production\n      MYSQL_ROOT_PASSWORD=\n      MYSQL_DATABASE=\n      MYSQL_USER=\n      MYSQL_PASSWORD=\n      SESSION_SECRET=\n      ```\n\n      **NOTE**: `NODE_ENV=production` is not needed since it is set with dockerfile, but adding it even though\n\n   - Modify `.profile` to load `.env`\n\n      ```sh\n      vim .profile\n      ```\n\n      ```vim\n      # Add this at the bottom\n      \n      set -o allexport; source $HOME/.env; set +o allexport \n      ```\n\n      **NOTE**: use `$HOME` (or) `$(pwd)` (or) `$PWD` (or) absolute path\n\n   - check existing environmental variables\n\n      ```sh\n      printenv\n      ```\n\n   - Exit and relogin again for the changes to take effect\n\n1. Create a folder for the code and clone it (ssh)\n\n    ```sh\n    mkdir app\n\n    cd app\n\n    git clone git@github.com:Mugilan-Codes/objection-knex-demo.git .\n    ```\n\n1. Run docker production command\n\n    ```sh\n    docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d\n    ```\n\n    - Run migrations inside the node-app container\n\n      ```sh\n      docker exec -it app_node-app_1 ash\n\n      npm run migrate:prod\n      ```\n\n    - Check in mysql container if the migrations where successfull\n\n      ```sh\n      docker exec -it app_mysql_1 mysql -u \u003cMYSQL_USER\u003e --password=\u003cMYSQL_PASSWORD\u003e\n      ```\n\n      ```sql\n      select database();\n\n      show databases;\n\n      use \u003cMYSQL_DATABASE\u003e;\n\n      select database();\n\n      show tables;\n\n      desc \u003ctable_name\u003e;\n      ```\n\n1. Make calls to the API from anywhere in the world\n\n     ```http\n     http://\u003cPUBLIC_IPV4_ADDRESS/PUBLIC_IPV4_DNS\u003e/api/v1\n     ```\n\n1. Workflow\n\n   - Make changes to src and push it to github\n\n   - `cd app` in production server and git pull the new changes\n\n   - Build the new image in production server\n\n      ```sh\n      docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build\n\n      # we know that there will be changes only in the node app so we can do this instead \n      docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build node-app\n\n      # do the above thing but without rebuilding the dependencies (depends_on)\n      docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build --no-deps node-app\n\n      # force rebuild containers even when there is no change without dependecies\n      docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d --force-recreate --no-deps node-app\n      ```\n\n   - Use a cloud repo to store the built images (**_DockerHub_** or amazon's ECR or something else..). Create a repository there.\n\n     - Tag the image with respect to the name on the remote image repo that was created. (`\u003cusername\u003e/\u003crepo_name\u003e`)\n\n        ```sh\n        docker image tag \u003clocal_image_name\u003e:\u003cversion\u003e \u003cusername\u003e/\u003crepo_name\u003e\n        \n        docker image tag objection-knex_node-app mugilancodes/objection-knex-node-app\n        ```\n\n        **NOTE**: if `version` is not provided it defaults to `latest`\n\n     - Push the tagged image to remote repo\n\n        ```sh\n        docker push \u003cusername\u003e/\u003crepo_name\u003e\n\n        docker push mugilancodes/objection-knex-node-app\n        ```\n\n     - Update docker-compose.yml file to use this `image`\n using `git push`\n\n      **NOTE**: Do these in the local development machine\n\n   - Pull in the changes using `git pull` and run the containers again in `production server` to tag the images\n\n      ```sh\n      docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d\n      ```\n\n   - How to make changes reflect in production server?\n\n     1. In Develoment Machine\n\n        - Build the custom images in local development machine\n\n          ```sh\n          docker-compose -f docker-compose.yml -f docker-compose.prod.yml build\n\n          # only specific service\n          docker-compose -f docker-compose.yml -f docker-compose.prod.yml build node-app\n          ```\n\n        - Push the built images to cloud image repo\n\n          ```sh\n          docker-compose -f docker-compose.yml -f docker-compose.prod.yml push\n\n          # only specific service\n          docker-compose -f docker-compose.yml -f docker-compose.prod.yml push node-app\n          ```\n\n     1. In Production Server\n\n        - Pull the changes from cloud repo into the production server\n\n          ```sh\n          docker-compose -f docker-compose.yml -f docker-compose.prod.yml pull\n\n          # only specific image\n          docker-compose -f docker-compose.yml -f docker-compose.prod.yml pull node-app\n          ```\n\n        - Update the changes\n\n          ```sh\n          docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d\n\n          # specific rebuild\n          docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d --no-deps node-app\n          ```\n\n        **NOTE**: use [watchtower](https://containrrr.dev/watchtower/) to automate these steps in production server\n\n1. Orchestrator (kubernetes or [**_docker swarm_**](https://docs.docker.com/engine/swarm/))\n\n   - Check if docker swarm is active in production server (`Swarm: active`)\n\n     ```sh\n     docker info\n     ```\n\n   - Activate Swarm\n\n     - Get public ip (`eth0 --\u003e inet`)\n\n       ```sh\n       ip add\n       ```\n\n     - Initialize swarm using the public ip\n\n       ```sh\n       docker swarm init --advertise-addr \u003cpublic_ip\u003e\n       ```\n\n   - Add Nodes to Swarm\n\n     - Manager\n\n       ```sh\n       docker swarm join-token manager\n       ```\n\n     - Worker\n\n       ```sh\n       docker swarm join --token \u003ctoken_provided\u003e \u003cip\u003e:\u003cport\u003e\n       \n       # retrieve the join command for the worker\n       docker swarm join-token worker\n       ```\n\n   - Update compose file for [swarm deployment](https://docs.docker.com/compose/compose-file/compose-file-v3/#deploy) and push it to github\n\n   - Pull in the changes made to production docker compose into production server. Tear down the running containers to prepare for docker stack deploy\n\n   - Deploy (you can choose any name for the Stack instead of `myapp`)\n\n      ```sh\n      docker stack deploy -c docker-compose.yml -c docker-compose.prod.yml myapp\n      ```\n\n      - check how many nodes are running\n\n         ```sh\n         docker node ls\n         ```\n\n      - check how many stacks are there\n\n         ```sh\n         docker stack ls\n         ```\n\n      - list the services in the stack\n\n         ```sh\n         docker stack services myapp\n         ```\n\n      - list all the services across all stacks\n\n         ```sh\n         docker service ls\n         ```\n\n      - list the tasks in the stack\n  \n         ```sh\n         docker stack ps myapp\n         ```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmugilan-codes%2Fobjection-knex-demo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmugilan-codes%2Fobjection-knex-demo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmugilan-codes%2Fobjection-knex-demo/lists"}