<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ajay</title>
    <description>The latest articles on DEV Community by Ajay (@ajay404).</description>
    <link>https://dev.to/ajay404</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1069254%2F143275c5-feac-4e11-8444-34cd445751a2.jpg</url>
      <title>DEV Community: Ajay</title>
      <link>https://dev.to/ajay404</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ajay404"/>
    <language>en</language>
    <item>
      <title>Overcoming NEXT_PUBLIC_ Environment Variable Limitations in Next.js with Docker</title>
      <dc:creator>Ajay</dc:creator>
      <pubDate>Sat, 21 Sep 2024 07:56:02 +0000</pubDate>
      <link>https://dev.to/ajay404/overcoming-nextpublic-environment-variable-limitations-in-nextjs-with-docker-5gh6</link>
      <guid>https://dev.to/ajay404/overcoming-nextpublic-environment-variable-limitations-in-nextjs-with-docker-5gh6</guid>
      <description>&lt;p&gt;When deploying a Next.js application in a Docker container, managing environment variables can be a real challenge — especially when it comes to client-side variables prefixed with &lt;code&gt;NEXT_PUBLIC_&lt;/code&gt;. This is crucial for services like Google reCAPTCHA and analytics tools like PostHog, which require these variables at runtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Issue: &lt;code&gt;NEXT_PUBLIC_&lt;/code&gt; Environment Variables and Docker
&lt;/h2&gt;

&lt;p&gt;Imagine you've successfully built your Next.js app locally, only to run into a wall when you try to deploy it in a Docker container. The problem arises because &lt;code&gt;NEXT_PUBLIC_&lt;/code&gt; environment variables must be defined at build time. When you run the &lt;code&gt;next build&lt;/code&gt; command, Next.js inlines these values into the generated JavaScript, making them inaccessible at runtime.&lt;/p&gt;

&lt;p&gt;In a typical setup where the same Docker image is used across multiple environments (dev, staging, production), this means you would need to create separate images for each environment just to accommodate different values for &lt;code&gt;NEXT_PUBLIC_&lt;/code&gt;. This approach leads to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Increased complexity in your CI/CD pipeline.&lt;/li&gt;
&lt;li&gt;Longer deployment times.&lt;/li&gt;
&lt;li&gt;A higher chance of introducing errors with each build.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, I encountered significant challenges when integrating PostHog for analytics, as I needed to provide the &lt;code&gt;NEXT_PUBLIC_POSTHOG_KEY&lt;/code&gt; in different environments without rebuilding the Docker image. Similarly, handling Google reCAPTCHA keys posed a similar issue.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: Dynamic Environment Variables with &lt;code&gt;next-runtime-env&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Fortunately, there's a way to avoid these headaches: using the &lt;code&gt;next-runtime-env&lt;/code&gt; package. This package allows you to inject environment variables into your Next.js application at runtime, enabling you to build your Docker image once and deploy it across different environments without needing to rebuild.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Get Started
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Install &lt;code&gt;next-runtime-env&lt;/code&gt;:&lt;/strong&gt; Add the package to your project:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   npm &lt;span class="nb"&gt;install &lt;/span&gt;next-runtime-env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Update Your Layout&lt;/strong&gt;: In your &lt;code&gt;app/layout.tsx&lt;/code&gt;, include the PublicEnvScript component to expose your &lt;code&gt;NEXT_PUBLIC_&lt;/code&gt; variables:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;// app/layout.tsx
import &lt;span class="o"&gt;{&lt;/span&gt; PublicEnvScript &lt;span class="o"&gt;}&lt;/span&gt; from &lt;span class="s1"&gt;'next-runtime-env'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nb"&gt;export &lt;/span&gt;default &lt;span class="k"&gt;function &lt;/span&gt;RootLayout&lt;span class="o"&gt;({&lt;/span&gt; children &lt;span class="o"&gt;}&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt; children: React.ReactNode &lt;span class="o"&gt;})&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
    &amp;lt;html &lt;span class="nv"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"en"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &amp;lt;&lt;span class="nb"&gt;head&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &amp;lt;PublicEnvScript /&amp;gt;
      &amp;lt;/head&amp;gt;
      &amp;lt;body&amp;gt;
        &lt;span class="o"&gt;{&lt;/span&gt;children&lt;span class="o"&gt;}&lt;/span&gt;
      &amp;lt;/body&amp;gt;
    &amp;lt;/html&amp;gt;
  &lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Access Your Variables:&lt;/strong&gt; Now you can access your environment variables within your components:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;// app/client-page.tsx
&lt;span class="s1"&gt;'use client'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
import &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;env&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt; from &lt;span class="s1"&gt;'next-runtime-env'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
import posthog from &lt;span class="s1"&gt;'posthog-js'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
import &lt;span class="o"&gt;{&lt;/span&gt; PostHogProvider &lt;span class="o"&gt;}&lt;/span&gt; from &lt;span class="s1"&gt;'posthog-js/react'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
import React from &lt;span class="s1"&gt;'react'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;typeof window &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="s2"&gt;"undefined"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  posthog.init&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;env&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"NEXT_PUBLIC_POSTHOG_KEY"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;, &lt;span class="o"&gt;{&lt;/span&gt;
    api_host: &lt;span class="s2"&gt;"/ingest"&lt;/span&gt;,
    ui_host: &lt;span class="s2"&gt;"https://us.posthog.com"&lt;/span&gt;,
    person_profiles: &lt;span class="s2"&gt;"always"&lt;/span&gt;,
  &lt;span class="o"&gt;})&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="k"&gt;function &lt;/span&gt;CSPostHogProvider&lt;span class="o"&gt;({&lt;/span&gt; children &lt;span class="o"&gt;}&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt; children: React.ReactNode &lt;span class="o"&gt;})&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &amp;lt;PostHogProvider &lt;span class="nv"&gt;client&lt;/span&gt;&lt;span class="o"&gt;={&lt;/span&gt;posthog&lt;span class="o"&gt;}&amp;gt;{&lt;/span&gt;children&lt;span class="o"&gt;}&lt;/span&gt;&amp;lt;/PostHogProvider&amp;gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Benefits of This Approach
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;One Image, Many Environments&lt;/strong&gt;: With &lt;code&gt;next-runtime-env&lt;/code&gt;, you can use a single Docker image across different environments, significantly simplifying your deployment strategy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Faster Deployments&lt;/strong&gt;: Since you're not rebuilding images, your deployments are quicker and less prone to errors.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Easier Maintenance&lt;/strong&gt;: You'll spend less time managing multiple builds, allowing you to focus on developing new features.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;If you've ever faced the challenge of managing &lt;code&gt;NEXT_PUBLIC_&lt;/code&gt;,environment variables in a Dockerized Next.js application, you know how frustrating it can be. By leveraging &lt;code&gt;next-runtime-env&lt;/code&gt;, you can manage these variables dynamically at runtime, ensuring a smooth and efficient deployment process.&lt;/p&gt;

&lt;p&gt;This solution keeps your Docker strategy simple, maintainable, and effective across all your environments — whether you're handling analytics tools like PostHog or integrating Google reCAPTCHA.&lt;/p&gt;

&lt;p&gt;May your code be bug-free!&lt;/p&gt;

</description>
      <category>docker</category>
      <category>webdev</category>
      <category>nextjs</category>
      <category>multistage</category>
    </item>
  </channel>
</rss>
