{"id":1256,"date":"2020-11-01T22:14:24","date_gmt":"2020-11-01T22:14:24","guid":{"rendered":"http:\/\/10.0.0.14\/?p=1256"},"modified":"2021-12-21T22:41:07","modified_gmt":"2021-12-21T22:41:07","slug":"tdd-with-gatsby-docker-part-1-setup-dev-env","status":"publish","type":"post","link":"https:\/\/tutorials.leesonresearch.com\/tutorials\/2020\/11\/01\/tdd-with-gatsby-docker-part-1-setup-dev-env\/","title":{"rendered":"TDD with Gatsby, Django &#038; Docker Part 2, Chapter 08 &#8212; Setup Gatsby Development Environment"},"content":{"rendered":"\n<h1 class=\"wp-block-heading\">Setting Up Our Dev Environment<\/h1>\n\n\n\n<p>Note that we are building on the Django Graphene project from Part 1 which will provide our backend for the Gatsby frontend to interface with.<\/p>\n\n\n\n<p>This chapter on setting up a Dockerized Gatsby environment is based on Aripalo&#8217;s elegant solution on Github.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Setting Up the Directory Structure<\/h4>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Double click to copy; notranslate\" title=\"Double click to copy\">\n# 1) Install Gatsby CLI on local computer\nnpm install -g gatsby-cli\n\n# 2) Generate Gatsby starter site\ngatsby new frontend https:\/\/github.com\/gatsbyjs\/gatsby-starter-hello-world\n\n# 3) Remove the Gatsby git resources since we will use our git installation at the root of our project\nrm -rf frontend\/.git\nrm -rf frontend\/.gitignore\n\n# 4) Remove node_modules from local computer since we will be installing the node modules on the Docker frontend container\nrm -rf frontend\/node_modules\n\n# 5) Create our frontend Dockerfile script\ntouch frontend\/Dockerfile\n\n# 6) Create a directory for Nginx\nmkdir nginx\n\n# 7) Create a Dockerfile and nginx.conf files for Nginx\ntouch nginx\/Dockerfile\ntouch nginx\/nginx.conf\n\n# 8) Create a new Docker Compose files for production and development\ntouch docker-compose.yml\ntouch docker-compose-dev.yml\n\n# 9) Initialize git repository\ngit init\n<\/pre><\/div>\n\n\n<p>This is how our current directory structure should look:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>todo_gatsby-django-graphene (directory  root of the project)<ul><li>frontend (directory)<ul><li>Dockerfile<\/li><\/ul><\/li><li>nginx (directory)<ul><li>Dockerfile<\/li><li>nginx.conf<\/li><\/ul><\/li><li>server (the Django Graphene app we created in Part 1)<\/li><li>docker-compose.yml<\/li><li>docker-compose-dev.yml<\/li><li>.env <\/li><li>.gitignore <\/li><li>Makefile<\/li><\/ul><\/li><\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">Populate Frontend Files<\/h4>\n\n\n\n<ol class=\"wp-block-list\"><li>Our goal is to build a todo application with Gatsby as  our frontend which will interface with the Django Graphene server we built in Part 1 of this tutorial. We start by installing the Gatsby CLI on our local computer which is the main entry point for setting Gatsby up on our computer.<\/li><li>We created a new Gatsby project using the Gatsby Hello World starter site which we renamed to <strong>frontend<\/strong>.<\/li><li>When Gatsby generated its own git repo which we don&#8217;t need since we already have our git repo at the root of our project. We also deleted the .gitignore from the <strong>frontend<\/strong> directory.<\/li><li>Create our <strong>frontend<\/strong> Dockerfile to configure the Gatsby env.<\/li><li>Create a directory for nginx.<\/li><li>Create a nginx\/Dockerfile and nginx\/nginx.conf file to configure Nginx server for our production build.<\/li><li>Create two Docker Compose files, one for deploying our Gatsby build to nginx which will serve our site using <a rel=\"noreferrer noopener\" href=\"https:\/\/medium.com\/@quinn.royston\/server-side-rendering-213f66b27229\" target=\"_blank\">SSR, (server side rendering)<\/a>, which comes with the Gatsby build.<\/li><li>Initialize our git repository for this project.<\/li><\/ol>\n\n\n\n<p>Lets begin by populating frontend Dockerfile.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Frontend Dockerfile<\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Double click to copy; notranslate\" title=\"Double click to copy\">\n# frontend\/Dockerfile\n\n# 1)\nFROM node:16-alpine\n\n# 2)\nEXPOSE 8000\n\n# 3)\nWORKDIR \/frontend\n\n# 4)\nRUN apk update &amp;amp;&amp;amp; apk add python3 g++ make &amp;amp;&amp;amp; rm -rf \/var\/cache\/apk\/*\n\n# 5)\nRUN npm install -g gatsby-cli\n\n# 6)\nCOPY . .\n\n# 7)\nRUN npm install\n\n# 8) Building Gatsby generating public directory that can be copied to Nginx service in production\nCMD &#x5B; &quot;gatsby&quot;, &quot;build&quot; ]\n<\/pre><\/div>\n\n\n<ol class=\"wp-block-list\"><li>Using node:16-alpine image we build our node environment. I&#8217;m specifying node version 16 here because Gatsby requires a minimum of node 14 for Gatsby 3.14.4 which is the latest version at the time of writing this blog. I found that Gatsby <\/li><li>Open a port on the frontend container.<\/li><li>Set the working directory with the WORKDIR Docker command. <strong>Doing this in one of the first layers is very important otherwise when we run npm install Gatsby will be installed at the root of the container instead of the working directory frontend. When we try running Gatsby commands such as Gatsby build, an error will be thrown saying that Gatsby is not installed. Declaring the WORKDIR early fixes this problem.<\/strong><\/li><li>Since Node.js is built with node-gyp which is written in Python we need Python installed. You can read more about this Python requirement for GYP <a rel=\"noreferrer noopener\" href=\"https:\/\/stackoverflow.com\/questions\/23709739\/why-does-node-js-need-python\" target=\"_blank\">here<\/a>.<\/li><li>Install Gatsby CLI.<\/li><li>Copy the contents of the frontend directory on the host machine into the frontend container that we are building. Note that in step 3 when we set the working directory with WORKDIR, Docker creates the frontend directory for us and cd into the frontend directory so all the subsequent commands are executing in the frontend directory.<\/li><li>Install all the packages defined in the package.json file.<\/li><li>Using the Dockerfile CMD we define the default command to set Gatsby into production mode which will serve the production build from the \/www\/public.<\/li><\/ol>\n\n\n\n<p>Now we can build the frontend container:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Double click to copy; notranslate\" title=\"Double click to copy\">\ndocker-compose build frontend\n<\/pre><\/div>\n\n\n<h5 class=\"wp-block-heading\">Notes on How I Built the Gatsby Frontend Dockerfile<\/h5>\n\n\n\n<p>I was not able to find much documentation on how to use Docker with Gatsby. Some of the Dockerfile solutions I did find didn&#8217;t work for me. I did find one solution by <a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/aripalo\/gatsby-docker\/\" target=\"_blank\">Ari Palo<\/a> that did work but seemed a bit complex so I decided to write my own with the intention of serving the Gatsby build with Nginx as a separate service.<\/p>\n\n\n\n<p>Building this Dockerfile was the most challenging part of this tutorial for me. I ran across many gotchas in the process. For example, Gatsby 3.14.4 will not work with the latest version of Node hence my use of node 16 which is compatible with Gatsby 3.14.4. As Gatsby keeps evolving this will probably change in the future.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Trouble Shooting Tips!<\/h4>\n\n\n\n<p>What proved invaluable for me in developing and sifting out all the errors was to use the <strong>Docker exec<\/strong> command to gain shell access to the frontend container and run each of the commands above in the shell of the container. This is the command I used to gain shell access to the running frontend container:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Double click to copy; notranslate\" title=\"Double click to copy\">\ndocker exec -it frontend ash\n<\/pre><\/div>\n\n\n<p>Running the commands manually in the container allowed me to catch two subtle issues that <strong>docker-compose logs<\/strong> <strong>frontend<\/strong> for the frontend container missed:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>The WORKDIR command has to run in one of the first layers so Gatsby will install in the frontend directory as opposed to the root of the container.<\/li><li>While running npm install I would get the error that node-gyp could not find Python so I needed to install Python <strong>before<\/strong> running npm install.<\/li><li>Manually running <strong>gatsby build<\/strong> directly in the container flagged two issues <ol><li>Gatsby requiring a minimum of node 14 for this version of Gatsby thus I was able through trial and error find the most recent version of node alpine that is compatible with Gatsby.<\/li><li>Gatsby was not installed in the working frontend directory.<\/li><\/ol><\/li><\/ol>\n\n\n\n<p>As I mentioned earlier, as Gatsby continues to evolve the issues I encountered will change so if you, dear reader, in the process of following this tutorial in the future run into problems, I encourage you to start with a bare bones version of a Dockerfile and manually run the each command incrementally so you can catch the errors as they occur with more verbose documentation than <strong>docker-compose logs frontend<\/strong> might give you.<\/p>\n\n\n\n<p>Here&#8217;s an example of a bare-bones Dockerfile to begin with:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Double click to copy; notranslate\" title=\"Double click to copy\">\nFROM node:16-alpine\n\nEXPOSE 8000\n\nWORKDIR \/frontend\n\nCMD tail -f \/dev\/null\n<\/pre><\/div>\n\n\n<p>Note the <strong>CMD tail -f \/dev\/null<\/strong> command. If we don&#8217;t have a Docker command specified the container will build itself and shut itself down so using <strong>CMD tail -f \/dev\/null<\/strong> keeps the container up and running allowing us shell access.<\/p>\n\n\n\n<p>From here spin up the container and start manually running subsequent commands such as installing python, installing gatsby-cli, etc.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Double click to copy; notranslate\" title=\"Double click to copy\">\ndocker-compose -f docker-compose.yml -f docker-compose-dev.yml up -d\n\n# gain shell access to the container\n# docker exec -it &#x5B;name of container] ash\ndocker exec -it frontend ash\n<\/pre><\/div>\n\n\n<p>Once we are able to hit Gatsby&#8217;s development frontend with <a rel=\"noreferrer noopener\" href=\"http:\/\/localhost:8000\" target=\"_blank\">http:\/\/localhost:8000<\/a> we can move on with building the Nginx service which will serve our Gatsby production build.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Nginx Dockerfile<\/h5>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Double click to copy; notranslate\" title=\"Double click to copy\">\n# nginx\/Dockerfile\n\n# 1)\nFROM nginx:alpine\n\n# 2)\nEXPOSE 80\n\n# 3)\nCOPY nginx.conf \/etc\/nginx\/conf.d\/default.conf\n<\/pre><\/div>\n\n\n<ol class=\"wp-block-list\"><li>We pull the nginx alpine image to build the Nginx service<\/li><li>Expose port 80 of the Docker container<\/li><li>Copy our nginx.conf file to the Docker container&#8217;s nginx conf.d directory where we tell Nginx where to serve the frontend build files from<\/li><\/ol>\n\n\n\n<h5 class=\"wp-block-heading\">Configure Nginx<\/h5>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Double click to copy; notranslate\" title=\"Double click to copy\">\n# nginx\/nginx.conf\n\nserver {\n  root \/frontend\/public;\n\n  location \/ {\n    index index.html;\n  }\n}\n<\/pre><\/div>\n\n\n<p>Next we update docker-compose.yml with our new frontend:<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Docker Compose<\/h5>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; highlight: [37,38,39,40,41,42,43,44,45,46,47,48,49,50]; title: Double click to copy; notranslate\" title=\"Double click to copy\">\n# docker-compose.yml\n\nversion: '3'\n \nservices:\n    database:\n        container_name: postgres\n        image: postgres:latest\n        environment:\n            - POSTGRES_DB=$DATABASE_NAME\n            - POSTGRES_USER=$DATABASE_USER\n            - POSTGRES_PASSWORD=$DATABASE_PASSWORD\n            - POSTGRES_PORT=$DATABASE_PORT\n        volumes:\n            #- .\/server\/initial.sql:\/docker-entrypoint-initdb.d\/initial.sql\n            - .\/server\/db_backups\/backup.sql:\/docker-entrypoint-initdb.d\/backup.sql\n            - postgres-data:\/var\/lib\/postgresql\/data\n \n    server:\n        build: .\/server\/\n        container_name: dj02\n        working_dir: \/var\/www\/server\n        ports:\n            - '$SERVER_PORT:$SERVER_PORT'\n        volumes:\n            - .\/server\/:\/var\/www\/server\n        command: python manage.py runserver 0.0.0.0:$SERVER_PORT\n        environment:\n            - DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE\n            - PGHOST=$DATABASE_HOST\n        env_file:\n            - .env\n        depends_on:\n            - database\n\n    \n    # 1)\n    frontend:\n        # 2)\n        build:\n            context: .\/frontend\n            dockerfile: Dockerfile\n        # 3)\n        ports:\n            - 8000:8000\n        # 4)\n        volumes:\n          - .\/frontend\/:\/frontend\n        # 5)\n        container_name: frontend\n        # 6)\n        depends_on:\n          - server\n\nvolumes:\n    postgres-data:\n<\/pre><\/div>\n\n\n<p>With our additions we are defining the frontend service for the development mode of our project.<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Name of service.<\/li><li>Tell docker-compose where the Dockerfile is for the frontend service.<\/li><li>Map the outside port 8000 to port 8000 the container&#8217;s port.<\/li><li>Map the \/frontend files from the frontend container onto our host machine which allows us to edit and save files from our host machine dynamically updating the files in the frontend container and triggers a browser hot-reload.<\/li><li>Give the container the name frontend<\/li><li>Using depends_on tell the frontend to wait for the server to finish launching<\/li><\/ol>\n\n\n\n<h5 class=\"wp-block-heading\">Development Docker Compose Override<\/h5>\n\n\n\n<p>To run Gatsby in development mode we override the docker-compose file with the docker-compose-dev file.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Double click to copy; notranslate\" title=\"Double click to copy\">\n# docker-compose-dev.yml\nversion: '3'\n\nservices:\n  frontend:\n    # 1)\n    command: gatsby develop --host 0.0.0.0 --port 8000\n<\/pre><\/div>\n\n\n<ol class=\"wp-block-list\"><li>The command: develop &#8211;host 0.0.0.0 &#8211;port 8000 sets Gatsby in development mode<\/li><\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">Booting Up the Development Environment for  Gatsby Frontend<\/h4>\n\n\n\n<p>To bring Gatsby up in development mode we need only run:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Double click to copy; notranslate\" title=\"Double click to copy\">\ndocker-compose -f docker-compose.yml -f docker-compose-dev.yml up\n<\/pre><\/div>\n\n\n<p>&#8230; which should allow you to hit <a href=\"http:\/\/localhost:8000\">http:\/\/localhost:8000<\/a> to view the frontend index page.<\/p>\n\n\n\n<p>If you were to edit the copy in the frontend index.js file:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Double click to copy; notranslate\" title=\"Double click to copy\">\nvi frontend\/src\/pages\/index.js\n# Edit the copy, close and save\n<\/pre><\/div>\n\n\n<p>The changes should show up immediately in the browser without having to do a manual refresh of your browser. Is this not cool?<\/p>\n\n\n\n<p>You should also be able to access the backend server we built in Part 1 at http:\/\/localhost:5555\/admin:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"636\" src=\"http:\/\/10.0.0.14\/wp-content\/uploads\/2020\/10\/django_admin_pt2-1024x636.png\" alt=\"\" class=\"wp-image-1218\" srcset=\"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-content\/uploads\/2020\/10\/django_admin_pt2-1024x636.png 1024w, https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-content\/uploads\/2020\/10\/django_admin_pt2-300x186.png 300w, https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-content\/uploads\/2020\/10\/django_admin_pt2-768x477.png 768w, https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-content\/uploads\/2020\/10\/django_admin_pt2-600x372.png 600w, https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-content\/uploads\/2020\/10\/django_admin_pt2-945x587.png 945w, https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-content\/uploads\/2020\/10\/django_admin_pt2.png 1155w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>If you get an error on this page or you can&#8217;t log in you need to run Django migrations and create a super user:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"700\" height=\"574\" src=\"http:\/\/10.0.0.14\/wp-content\/uploads\/2020\/06\/initial_bootup_error.jpg\" alt=\"\" class=\"wp-image-328\" srcset=\"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-content\/uploads\/2020\/06\/initial_bootup_error.jpg 700w, https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-content\/uploads\/2020\/06\/initial_bootup_error-300x246.jpg 300w, https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-content\/uploads\/2020\/06\/initial_bootup_error-600x492.jpg 600w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><\/figure>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Double click to copy; notranslate\" title=\"Double click to copy\">\ndocker-compose run server .\/manage.py makemigrations\ndocker-compose run server .\/manage.py migrate\ndocker-compose run server .\/manage.py createsuperuser\n<\/pre><\/div>\n\n\n<h4 class=\"wp-block-heading\">Booting Up the Production Environment for Gatsby Frontend and the Django Backend Server<\/h4>\n\n\n\n<p>To boot up, build and deploy run:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Double click to copy; notranslate\" title=\"Double click to copy\">\ndocker-compose build frontend\ndocker-compose up -d\n<\/pre><\/div>\n\n\n<p>This command invokes the frontend Dockerfile which will run the Gatsby build command to compile the site into files that can be delivered to a web browser later.<\/p>\n\n\n\n<p>You should be able to access the production version being served by Nginx at http:\/\/localhost:8080.<\/p>\n\n\n\n<p>As well you should be able to access the Django server as well at http:\/\/localhost:5555\/admin.<\/p>\n\n\n\n<p>To power down the production environment run:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Double click to copy; notranslate\" title=\"Double click to copy\">\ndocker-compose down\n<\/pre><\/div>\n\n\n<h4 class=\"wp-block-heading\">Trouble Shooting<\/h4>\n\n\n\n<p>If you have trouble booting up all the docker services successfully with <strong>docker-compose up -d<\/strong> or the development override command <strong>docker-compose -f docker-compose.yml -f docker-compose-dev.yml up -d<\/strong> you can always try booting up each service separately because sometimes the Docker Compose depends_on attribute doesn&#8217;t always work so the server may boot up before Postgres service is ready to accept connections.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Double click to copy; notranslate\" title=\"Double click to copy\">\ndocker-compose up -d database\ndocker-compose up -d server\ndocker-compose up -d nginx\n\n# for the Gatsby development server\ndocker-compose -f docker-compose.yml -f docker-compose-dev.yml up -d\n<\/pre><\/div>\n\n\n<p>After running these commands you should be able to hit each of the different services this app is using via the browser:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Production frontend: <a href=\"http:\/\/localhost:8080\" target=\"_blank\" rel=\"noreferrer noopener\">http:\/\/localhost:8080<\/a><\/li><li>Development frontend, (if using the docker compose override): <a href=\"http:\/\/localhost:8000\" target=\"_blank\" rel=\"noreferrer noopener\">http:\/\/localhost:8000<\/a><\/li><li>Django admin: <a href=\"http:\/\/localhost:5555\/admin\" target=\"_blank\" rel=\"noreferrer noopener\">http:\/\/localhost:5555\/admin<\/a><\/li><li>Django graphql playground: <a href=\"http:\/\/localhost:5555\/graphql\" target=\"_blank\" rel=\"noreferrer noopener\">http:\/\/localhost:5555\/graphql<\/a><\/li><\/ul>\n\n\n\n<p>Since the docker compose commands are a bit cumbersome we can populate our Makefile with shortcut commands for development and production processes:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Double click to copy; notranslate\" title=\"Double click to copy\">\n# Makefile\n\ndev:\n  docker-compose up -d \n\nprod:\n  docker-compose -f docker-compose.yml -f docker-compose-prod.yml up -d\n\nprod-down:\n  docker-compose down --remove-orphans\n\n# Production Build\nprod-build:\n  docker-compose -f docker-compose.yml -f docker-compose-prod.yml build\n<\/pre><\/div>\n\n\n<p>Now if we want to boot up the production environment we need only run:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Double click to copy; notranslate\" title=\"Double click to copy\">\nmake prod\n<\/pre><\/div>\n\n\n<p>To power down simply:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Double click to copy; notranslate\" title=\"Double click to copy\">\nmake prod-down\n<\/pre><\/div>\n\n\n<p>To power up the development environment we run:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Double click to copy; notranslate\" title=\"Double click to copy\">\nmake dev\n<\/pre><\/div>\n\n\n<p>To power down the development environment:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Double click to copy; notranslate\" title=\"Double click to copy\">\nmake dev-down\n<\/pre><\/div>\n\n\n<p>Now that we have both development and production environments for Gatsby operational as well as the Django Graphene server operational &#8212; we can push on to the actual development of building out our frontend user interface.<\/p>\n\n\n\n<p>How do we know we haven&#8217;t broken anything with our server while setting up our frontend development environment. We could manually test the Django admin, and \/ or run ALL the Django queries and mutations in Django&#8217;s GraphiQL UI. Ugh!<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Testing the Django Graphene Server<\/h4>\n\n\n\n<p>But have we broken anything in the backend in the process of building the frontend? Easy enough to find out. We need only to run our unit tests.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Double click to copy; notranslate\" title=\"Double click to copy\">\ndocker-compose run server pytest\n<\/pre><\/div>\n\n\n<p>Voila! Our tests will tell us what and where if we have any failing tests. In my case all my tests passed. This gives me enormous confidence moving forward with the development of our frontend site.<\/p>\n\n\n\n<p>We will continue in our next chapter using TDD for Gatsby.<\/p>\n\n\n\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link\" href=\"tdd-with-django-graphene-docker-part-7-backup-db-makefile\">&lt; Previous:  Chapter 7<\/a><\/div>\n\n\n\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link\" href=\"tdd-with-gatsby-django-docker-part-2-chapter-9-configure-apollo-client\">Next: Chapter 9 &gt;<\/a><\/div>\n<\/div>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Using test driven development (TDD), with Gatsby and  Docker.<\/p>\n","protected":false},"author":1,"featured_media":277,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[20,12],"tags":[3,21,40,10],"class_list":["post-1256","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-featured-tutorial","category-gatsby","tag-docker","tag-docker-compose","tag-dockerfile","tag-gatsby"],"_links":{"self":[{"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/posts\/1256","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/comments?post=1256"}],"version-history":[{"count":106,"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/posts\/1256\/revisions"}],"predecessor-version":[{"id":2683,"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/posts\/1256\/revisions\/2683"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/media\/277"}],"wp:attachment":[{"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/media?parent=1256"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/categories?post=1256"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/tags?post=1256"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}