{"id":40,"date":"2020-05-14T21:35:21","date_gmt":"2020-05-14T21:35:21","guid":{"rendered":"http:\/\/localhost\/?p=40"},"modified":"2021-08-18T21:36:25","modified_gmt":"2021-08-18T21:36:25","slug":"dockerizing-gatsby","status":"publish","type":"post","link":"https:\/\/tutorials.leesonresearch.com\/tutorials\/2020\/05\/14\/dockerizing-gatsby\/","title":{"rendered":"Dockerizing Gatsby"},"content":{"rendered":"\n<h2 class=\"css-83xdrr-subTitle wp-block-heading\">Setting up Docker development and production environments for Gatsby.<\/h2>\n\n\n\n<p><a href=\"https:\/\/gitlab.com\/ronleeson\/dockerizing-gatsby.git\" target=\"_blank\" rel=\"noopener noreferrer\">Download the repo<\/a><\/p>\n\n\n\n<h3 class=\"css-83xdrr-subTitle wp-block-heading\">Docker is the Future<\/h3>\n\n\n\n<p>I love it. I&#8217;ve had experiences where it has taken hours to setup a new development environment on my Mac for an application requiring multiple services with their dependencies and configure it all to play nice on my OS. If I have to bring a new developer onto the team then I have to do this all over again working for hours walking through a complex series of steps to setup the new team member&#8217;s environment on their OS. Docker eliminates all that. All that is required to spin up a complete development environment with all the apps dependencies is to pull your app from the DockerHub repository or from your git repo, cd to the root of your project and launch your app from the terminal. Sweet&#8230;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What is Docker?<\/h3>\n\n\n\n<p>Quoting from Wikipeda:<\/p>\n\n\n\n<blockquote><p><b>Docker<\/b>&nbsp;is a set of platform as a service (PaaS) products that uses OS-level virtualization to deliver software in packages called containers. Containers are isolated from one another and bundle their own software, libraries and configuration files; they can communicate with each other through well-defined channels. All containers are run by a single operating system kernel and therefore use fewer resources than virtual machines.<\/p><\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\">Why Docker?<\/h3>\n\n\n\n<blockquote><p><em>Containers are a standardized unit of software that allows developers to isolate their app from its environment, solving the \u201cit works on my machine\u201d headache.<\/em><\/p><\/blockquote>\n\n\n\n<p><\/p>\n\n\n\n<p>Once you build your Dockerized app it will work anywhere.<\/p>\n\n\n\n<p>To install Docker go to the&nbsp;<a rel=\"noreferrer noopener\" href=\"https:\/\/docs.docker.com\/get-docker\/\" target=\"_blank\">Docker installation docs<\/a>&nbsp;and they will walk you through the process for your particular OS.<\/p>\n\n\n\n<p>Along with Docker we will also be using Docker Compose.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What is Docker Compose?<\/h3>\n\n\n\n<p>Here&#8217;s an excerpt from the official Docker docs giving an&nbsp;<a rel=\"noreferrer noopener\" href=\"https:\/\/docs.docker.com\/compose\/\" target=\"_blank\">Overview of Docker Compose.<\/a><\/p>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow\">\n<blockquote>\n<p>Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application\u2019s services. Then, with a single command, you create and start all the services from your configuration. To learn more about all the features of Compose, see the list of features.<br><br>Compose works in all environments: production, staging, development, testing, as well as CI workflows. You can learn more about each case in Common Use Cases.<br><br>Using Compose is basically a three-step process:<\/p>\n<ol>\n<li>Define your app\u2019s environment with a Dockerfile so it can be reproduced anywhere.<\/li>\n<li>Define the services that make up your app in docker-compose.yml so they can be run together in an isolated environment.<\/li>\n<li>Run docker-compose up and Compose starts and runs your entire app.<\/li>\n<\/ol>\n<\/blockquote>\n<\/div><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">What is Gatsby?<\/h3>\n\n\n\n<p>Gatsby weaves together ReactJS, GraphQL, webpack and more.<\/p>\n\n\n\n<p>Since this is not a blog about Gatsby in particular I won&#8217;t go into the detail of the how and why of using Gatsby.&nbsp;<a rel=\"noreferrer noopener\" href=\"https:\/\/www.gatsbyjs.org\/\" target=\"_blank\">Gatsby&#8217;s site will tell you all you need to know here<\/a>.<\/p>\n\n\n\n<p>Once you have Docker and Gatsby installed on your system, we can jump into the Dockerization of a simple Gatsby &#8220;hello world&#8221; starter site.<\/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<p>As we proceed we will be drawing heavily on <a href=\"https:\/\/github.com\/aripalo\/gatsby-docker\/\" target=\"_blank\" rel=\"noreferrer noopener\">Aripalo&#8217;s elegant solution on Github on how to Dockerize Gatsby<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Create Our Project!<\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: powershell; title: Double click to copy; notranslate\" title=\"Double click to copy\">\nmkdir my-dockerized-gatsby\ncd my-dockerized-gatsby\ntouch docker-compose-dev.yml\ntouch docker-compose.yml\ntouch Makefile\ngit init\n<\/pre><\/div>\n\n\n<h6 class=\"wp-block-heading\">Our file structure<\/h6>\n\n\n\n<ul>\n<li>\n\nmy-dockerized-gatsby\n<ul>\n<li>\nfrontend<\/li>\n<li>\ndocker-compose-dev.yml<\/li>\n<li>\ndocker-compose.yml<\/li>\n\nMakefile<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Setup Gatsby<\/h3>\n\n\n\n<p>Install Gatsby hello world starter site<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: Double click to copy; notranslate\" title=\"Double click to copy\">\ngatsby new gatsby-starter-hello-world https:\/\/github.com\/gatsbyjs\/gatsby-starter-hello-world\n<\/pre><\/div>\n\n\n<p>Rename Gatsby starter from gatsby-starter-hello-world to frontend.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: Double click to copy; notranslate\" title=\"Double click to copy\">\nmv gatsby-starter-hello-world frontend\ncd frontend\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Setup Dockerfile<\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: Double click to copy; notranslate\" title=\"Double click to copy\">\ncd frontend\nnano Dockerfile\n<\/pre><\/div>\n\n\n<p>Add the following to our Dockerfile.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: Double click to copy; notranslate\" title=\"Double click to copy\">\n# \/my-dockerized-gatsby\/frontend\/Dockerfile\n\nFROM node:10-alpine\n\nCOPY .\/entry.sh \/\nCOPY nginx.conf \/etc\/nginx\/conf.d\/default.conf\n\nRUN apk add --no-cache \\\n      nginx \\\n      python \\\n      build-base \\\n    &amp;&amp; npm install --global --no-optional gatsby@2.19.12  \\\n    &amp;&amp; mkdir -p \/www \/run\/nginx \\\n    &amp;&amp; chmod +x \/entry.sh \\\n    &amp;&amp; ln -sf \/dev\/stdout \/var\/log\/nginx\/access.log \\\n    &amp;&amp; ln -sf \/dev\/stderr \/var\/log\/nginx\/error.log\n\nWORKDIR \/www\nEXPOSE 80\n\nCOPY . \/www\nRUN npm install\nRUN gatsby build\n\nENTRYPOINT &#x5B; &quot;\/entry.sh&quot; ]\nCMD &#x5B; &quot;serve-nginx&quot; ]\n\n<\/pre><\/div>\n\n\n<p>You can skip the in-depth explanation and&nbsp;<a href=\"http:\/\/localhost:8000\/docker-gatsby_tpl\/#entry-sh\">go directly to the entry.sh file<\/a>.<\/p>\n\n\n\n<p>What&#8217;s going on here? When we run docker-compose, (more on that later), the Dockerfile is going to build the Gatsby server.<\/p>\n\n\n\n<p>Let&#8217;s walk through this step by step.<\/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# \/my-dockerized-gatsby\/frontend\/Dockerfile\n\nFROM node:10-alpine\n<\/pre><\/div>\n\n\n<p>Using the FROM directive we pull our base Node.js Alpine image. Alpine is a lightweight Linux distribution and Node.js is a javascript server environment.<\/p>\n\n\n\n<p><a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/alpine-docker\/node\" target=\"_blank\">More about alpine-docker\/node here<\/a>.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: Double click to copy; notranslate\" title=\"Double click to copy\">\n# \/my-dockerized-gatsby\/frontend\/Dockerfile\n\nCOPY .\/entry.sh \/\nCOPY nginx.conf \/etc\/nginx\/conf.d\/default.conf\n<\/pre><\/div>\n\n\n<p>We copy our entry.sh nginx files, (which we have yet to create), from the current directory to our node server on our Docker 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\">\n# \/my-dockerized-gatsby\/frontend\/Dockerfile\n\nRUN apk add --no-cache \\\n      nginx \\\n      python \\\n      build-base \\\n    &amp;amp;&amp;amp; npm install --global --no-optional gatsby@2.19.12  \\\n    &amp;amp;&amp;amp; mkdir -p \/www \/run\/nginx \\\n    &amp;amp;&amp;amp; chmod +x \/entry.sh \\\n    &amp;amp;&amp;amp; ln -sf \/dev\/stdout \/var\/log\/nginx\/access.log \\\n    &amp;amp;&amp;amp; ln -sf \/dev\/stderr \/var\/log\/nginx\/error.log\n<\/pre><\/div>\n\n\n<p>Using the Docker RUN command we install the following packages<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>nginx web server<\/li><li>python<\/li><li>build-base which is a meta-package that installs the GCC, libc-dev and binutils packages<\/li><\/ul>\n\n\n\n<p>&amp;&amp; run additional commands installing Gatsby and configuring the server<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>install Gatsby from the npm software registry<\/li><li>mkdir -p&nbsp;<strong>**<\/strong>&nbsp;experiment with this mkdir -p \/www \/foo\/bar<\/li><li>chmod +x \/entry.sh which makes the entry.sh file an executable<\/li><li>create softlinks for messages and errors to access and error logs<\/li><\/ul>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: Double click to copy; notranslate\" title=\"Double click to copy\">\n# \/my-dockerized-gatsby\/frontend\/Dockerfile\n.\n.\n.\nENTRYPOINT &#x5B; &quot;\/entry.sh&quot; ]\nCMD &#x5B; &quot;serve-nginx&quot; ]\n<\/pre><\/div>\n\n\n<ul class=\"wp-block-list\"><li>ENTRYPOINT is a command telling docker to run the entry.sh script<\/li><li>CMD [ &#8220;serve-nginx&#8221; ], Docker command setting the default parameter to &#8220;serve-nginx&#8221;<\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Create the \/my-dockerized-gatsby\/frontend\/entry.sh shell script<\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: Double click to copy; notranslate\" title=\"Double click to copy\">\ntouch entry.sh\nnano entry.sh\n<\/pre><\/div>\n\n\n<p>Add the following to the entry.sh file.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: Double click to copy; notranslate\" title=\"Double click to copy\">\n#!\/bin\/sh\n\n# \/snippet_repo\/frontend\/entry.sh\n\nset -e\nexport PATH=$PATH:\/usr\/local\/bin\/gatsby\n\nif &#x5B; &quot;$1&quot; == &quot;serve-nginx&quot; ]; then\n  nginx -g &quot;daemon off;&quot;\nelse\n  gatsby $@\nfi\n<\/pre><\/div>\n\n\n<p>What<strong> <\/strong>is going on in our entry.sh file?<\/p>\n\n\n\n<blockquote><p><strong>if [ &#8220;$1&#8221; == &#8220;serve-nginx&#8221; ]; then<\/strong><em><br>if the positional argument $1 is &#8220;serve-nginx&#8221; then do something&#8230; which poses the question when would the postional argument not be &#8220;serve-nginx&#8221;? Ok, so&nbsp;<\/em><a rel=\"noreferrer noopener\" href=\"http:\/\/www.gnu.org\/savannah-checkouts\/gnu\/bash\/manual\/bash.html#Positional-Parameters\" target=\"_blank\">what are positional arguments?<\/a><\/p><\/blockquote>\n\n\n\n<p>What is going on here is if we are in the production environment serve the built Gatsby code then serve from Nginx.<\/p>\n\n\n\n<p>If we are in the development environment then we use Gatsby to serve the code.<\/p>\n\n\n\n<p>What determines which enviroment is set will be determined by the d<strong>ocker-compose<\/strong> files which we will build shortly, which will override the default Docker CMD.<\/p>\n\n\n\n<blockquote class=\"is-layout-flow wp-block-quote-is-layout-flow\"><p><strong>3.4.1 Positional Parameters<\/strong><\/p><p><em>A positional parameter is a parameter denoted by one or more digits, other than the single digit 0. Positional parameters are assigned from the shell\u2019s arguments when it is invoked, and may be reassigned using the set builtin command. Positional parameter N may be referenced as ${N}, or as $N when N consists of a single digit. Positional parameters may not be assigned to with assignment statements. The set and shift builtins are used to set and unset them (see Shell Builtin Commands). The positional parameters are temporarily replaced when a shell function is executed (see Shell Functions). When a positional parameter consisting of more than a single digit is expanded, it must be enclosed in braces.<\/em><\/p><\/blockquote>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: Double click to copy; notranslate\" title=\"Double click to copy\">\n# \/snippet_repo\/frontend\/entry.sh\n\n  nginx -g &quot;daemon off;&quot;\n<\/pre><\/div>\n\n\n<p><strong>then nginx -g &#8220;daemon off&#8221;<\/strong>, what&#8217;s the difference between nginx daemon on and daemon off?<\/p>\n\n\n\n<p>According to stack-overflow:<\/p>\n\n\n\n<blockquote>\n<p>For normal production (on a server), use the default daemon on; directive so the Nginx server will start in the background. In this way Nginx and other services are running and talking to each other. One server runs many services.<br><br>\nFor Docker containers (or for debugging), the daemon off; directive tells Nginx to stay in the foreground. For containers this is useful as best practice is for one container = one process. One server (container) has only one service.<\/p>\n<\/blockquote>\n\n\n\n<p><\/p>\n\n\n\n<p>Aha! Makes sense to me. \ud83d\ude42<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Create Nginx config file<\/h3>\n\n\n\n<p>Last piece of the puzzle for the frontend is the configuration Nginx to serve the Gatsby build files.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: Double click to copy; notranslate\" title=\"Double click to copy\">\ntouch nginx.conf\n<\/pre><\/div>\n\n\n<p>Add the following to nginx.conf.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: Double click to copy; notranslate\" title=\"Double click to copy\">\n# \/snippet_repo\/frontend\/nginx.conf\n\nserver {\n    root \/www\/public;\n\n    location \/ {\n        index index.html;\n    }\n}\n<\/pre><\/div>\n\n\n<p>We are telling Nginx that root where our frontend build files live resides at \/www\/public.<\/p>\n\n\n\n<p><strong>\/www\/public<\/strong>? Where in the cyber ether does that exist?<\/p>\n\n\n\n<p>Remember those empty docker-compose files we created earlier? Those docker-compose files will be our next step in the Dockerization of Gatsby. Onward!<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Setup Docker Compose<\/h3>\n\n\n\n<ol class=\"wp-block-list\"><li><strong>docker-compose.yml<\/strong>&nbsp;for all the services and telling Nginx to serve the Gatsby build files<\/li><li><strong>docker-compose-dev.yml<\/strong>&nbsp;for the development environment using the Gatsby development server<\/li><\/ol>\n\n\n\n<p>Let&#8217;s start with the&nbsp;<strong>docker-compose.yml<\/strong>&nbsp;file first.<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Define your app\u2019s environment with a Dockerfile.&nbsp;<strong>Done that!<\/strong><\/li><li>Define the services that make up your app in docker-compose.yml so they can be run together in an isolated environment.<\/li><\/ol>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: Double click to copy; notranslate\" title=\"Double click to copy\">\n# \/snippet_repo\/docker-compose.yml\n\nversion: '3'\n\nservices:\n    frontend:\n<\/pre><\/div>\n\n\n<p>In the above we define our frontend service.<\/p>\n\n\n\n<p>Next we need to tell Docker where the frontend Dockerfile lives which will commence the building of the frontend isolated environment.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: Double click to copy; notranslate\" title=\"Double click to copy\">\n# \/snippet_repo\/docker-compose.yml\n\nversion: '3'\n\nservices:\n    frontend:\n        build: .\/frontend\n<\/pre><\/div>\n\n\n<p>Since our frontend service is running in a isolated environment we need to tell Docker to expose an external port that maps to the internal port that our frontend service is serving from. In this case that would be&nbsp;<strong>exposing port 8000 mapping to the internal port 80<\/strong>. The exposed port can be any port you like as long as the port number you choose doesn&#8217;t conflict with any of the other services that we will be running in the app.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: Double click to copy; notranslate\" title=\"Double click to copy\">\n# \/snippet_repo\/docker-compose.yml\n\nversion: '3'\n\nservices:\n    frontend:\n        build: .\/frontend\n        ports:\n            - 8000:80\n<\/pre><\/div>\n\n\n<p>Specify a custom container name, rather than a generated default name and we&#8217;re done.<\/p>\n\n\n\n<p>Here&#8217;s the finished&nbsp;<strong>docker-compose.yml<\/strong>&nbsp;file.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: Double click to copy; notranslate\" title=\"Double click to copy\">\n# \/snippet_repo\/docker-compose.yml\n\nversion: '3'\n\nservices:\n    frontend:\n        build: .\/frontend\n        ports:\n            - 8000:80\n        container_name: frontend\n\n<\/pre><\/div>\n\n\n<p>Now we&#8217;re done with the&nbsp;<strong>docker-compose.yml<\/strong>&nbsp;file which is the production compose file used to fire up the built server-side-rendered Gatsby site.<\/p>\n\n\n\n<p>Next we build&nbsp;<strong>docker-compose-dev.yml<\/strong>, the compose file to fire up the Gatsby development server.<\/p>\n\n\n\n<p>In the&nbsp;<strong>docker-compose-dev.yml<\/strong>&nbsp;we need to override the&nbsp;<strong>docker-compose.yml<\/strong>&nbsp;file with additional service options:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>command<\/li><li>volumes<\/li><\/ul>\n\n\n\n<p>Using&nbsp;<strong>command<\/strong>&nbsp;we can override the default command in the Dockerfile:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: Double click to copy; notranslate\" title=\"Double click to copy\">\n# \/snippet_repo\/frontend\/Dockerfile\n.\n.\n.\nCMD &#x5B; &quot;serve-nginx&quot; ]\n<\/pre><\/div>\n\n\n<p>CMD [ &#8220;serve-nginx&#8221; ] # is the default command which tells the&nbsp;<strong>entry.sh<\/strong>&nbsp;file serve the Gatsby built files from Nginx. But when we are in our development environment we want to serve from the Gatsby development server.<\/p>\n\n\n\n<p>Note the conditional in the&nbsp;<strong>entry.sh<\/strong>&nbsp;file, if $1 == &#8220;serve-nginx&#8221;. We are going to use the&nbsp;<strong>docker-compose.yml<\/strong>&nbsp;command service option to set a new default command&nbsp;<strong>develop &#8211;host 0.0.0.0 &#8211;port 80<\/strong>&nbsp;which tells Gatsby to listen to requests from outside the docker container on port 80.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: Double click to copy; notranslate\" title=\"Double click to copy\">\n# \/snippet_repo\/frontend\/entry.sh\n.\n.\n.\n# When the starting docker from the\n# docker-compose-dev.yml file\n# the $1 variable == develop --host 0.0.0.0 --port 80\nif &#x5B; &quot;$1&quot; == &quot;serve-nginx&quot; ]; then\n  nginx -g &quot;daemon off;&quot;\nelse\n  # the $@ concatenates the docker-compose-dev command\n  # develop --host 0.0.0.0 --port 80 with gatsby\n  # which echos gatsby develop --host 0.0.0.0 --port 80\n  gatsby $@\nfi\n<\/pre><\/div>\n\n\n<p>So, back to the&nbsp;<strong>docker-compose-dev.yml<\/strong>&nbsp;file, we add our command override.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: Double click to copy; notranslate\" title=\"Double click to copy\">\n# \/snippet_repo\/docker-compose-dev.yml\n\nversion: '3'\n\nservices:\n  frontend:\n    command: develop --host 0.0.0.0 --port 80\n<\/pre><\/div>\n\n\n<p>Next we use the volumes option to copy the frontend files over to the docker container.<\/p>\n\n\n\n<p>Below is our completed&nbsp;<strong>docker-compose-dev.yml<\/strong>&nbsp;file.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: Double click to copy; notranslate\" title=\"Double click to copy\">\n# \/snippet_repo\/docker-compose-dev.yml\n\nversion: '3'\n\nservices:\n  frontend:\n    command: develop --host 0.0.0.0 --port 80\n    volumes:\n      - .\/frontend:\/www\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Launch Our Dockerized Gatsby Site<\/h3>\n\n\n\n<p>To launch our Gatsby site in development mode, make sure that you are at the projects root then use the following docker-compose command<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; 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<\/pre><\/div>\n\n\n<p>Note that we are invoking the production docker-compose.yml file and then overriding the docker production service options with our addition options from our docker-compose-dev.yml file.<\/p>\n\n\n\n<p>To build and launch the production enviroment use the following command.<\/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\n<\/pre><\/div>\n\n\n<p>After launching either enviroments you can use the following docker logs command to monitor the launch process which will give access to any errors if they should pop up.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: Double click to copy; notranslate\" title=\"Double click to copy\">\ndocker-compose logs frontend\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Build the Makefile<\/h3>\n\n\n\n<p>If you haven&#8217;t created a Makefile file in your project root, do so now.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: Double click to copy; notranslate\" title=\"Double click to copy\">\ntouch Makefile\n<\/pre><\/div>\n\n\n<p>Add the following to your Makefile.<\/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# \/my-dockerized-gatsby\/Makefile\n\nbuild:\n    docker-compose build\n\nprod:\n    docker-compose up -d\n\ndev:\n    docker-compose -f docker-compose.yml -f docker-compose-dev.yml up -d\n\nup-non-daemon:\n    docker-compose up\n\nstart:\n    docker-compose start\n\nstop:\n    docker-compose stop\n\ndown:\n    docker-compose down\n\nrestart:\n    docker-compose stop &amp;amp;&amp;amp; docker-compose start\n\nrestart-dev:\n    docker-compose down &amp;amp;&amp;amp; docker-compose -f docker-compose.yml -f docker-compose-dev.yml up -d\n\nrestart-frontend:\n    docker-compose stop frontend &amp;amp;&amp;amp; docker-compose start frontend\n<\/pre><\/div>\n\n\n<p>Now if you want to launch Gatsby from the development enviroment you can use the command make dev instead of the versbose <strong>docker-compose -f docker-compose.yml -f docker-compose-dev.yml up -d<\/strong>.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: Double click to copy; notranslate\" title=\"Double click to copy\">\nmake dev\n<\/pre><\/div>\n\n\n<p>Or to launch in the production environment make prod instead of <strong>docker-compose up -d<\/strong>.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: Double click to copy; notranslate\" title=\"Double click to copy\">\nmake prod\n<\/pre><\/div>\n\n\n<p>Voila! We are ready to develop with our new dockerized Gatsby environment.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Set up a Docker development and production environments for Gatsby with docker-compose.<\/p>\n","protected":false},"author":1,"featured_media":42,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[23,13,12],"tags":[3,21,10],"class_list":["post-40","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-boiler-plates","category-docker","category-gatsby","tag-docker","tag-docker-compose","tag-gatsby"],"_links":{"self":[{"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/posts\/40","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=40"}],"version-history":[{"count":70,"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/posts\/40\/revisions"}],"predecessor-version":[{"id":2412,"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/posts\/40\/revisions\/2412"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/media\/42"}],"wp:attachment":[{"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/media?parent=40"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/categories?post=40"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/tags?post=40"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}