<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="133712" data-post-id="133712">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="cnck1387" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  cnck1387
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I modified my <code>package.json</code> to grab <code>phoenix</code> and <code>phoenix_html</code> straight from npm as a regular package.</p>
<p>You can find them at:</p>
<ul>
<li><a href="https://www.npmjs.com/package/phoenix" rel="noopener nofollow ugc">https://www.npmjs.com/package/phoenix</a></li>
<li><a href="https://www.npmjs.com/package/phoenix_html" rel="noopener nofollow ugc">https://www.npmjs.com/package/phoenix_html</a></li>
</ul>
<p>And you can use them like normal in your JS, such as: <code>import "phoenix";</code>. Assuming you’re using ES6 style JS.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="133712" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/multi-stage-docker-image-for-phoenix/23427/23">Post #22</a>
	                </div>
	            </div>
              <div id="likers-container-133712" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="133712"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #22"></div>
  </section>
</div>
    <div class="postbit" id="133714" data-post-id="133714">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="egze" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/egze/120/13522_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  egze
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Doh. I had no idea they are available in npm.</p>
<p>Thanks a lot!</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="133714" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/multi-stage-docker-image-for-phoenix/23427/24">Post #23</a>
	                </div>
	            </div>
              <div id="likers-container-133714" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="133714"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #23"></div>
  </section>
</div>
    <div class="postbit" id="133715" data-post-id="133715">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="cnck1387" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  cnck1387
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>No problem. It took a while to wire all of that together, but now that it works, it’s really nice. It’s a setup that will work in both dev and prod using the same <code>docker-compose.yml</code> file because in prod I just wouldn’t use the <code>docker-compose.override.yml</code> file, because in prod nginx would serve the compiled assets instead of running the webpack dev server.</p>
<p>That behavior is dictated by the build args that you can set with ENV variables.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="133715" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/multi-stage-docker-image-for-phoenix/23427/25">Post #24</a>
	                </div>
	            </div>
              <div id="likers-container-133715" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="133715"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #24"></div>
  </section>
</div>
    <div class="postbit" id="133724" data-post-id="133724">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="chulkilee" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/chulkilee/120/6207_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  chulkilee
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I really wish <code>mix deps.get</code> and <code>mix deps.compile</code> work <em>only with</em> <code>mix.lock</code> (see <a href="https://forum.elixirforum.com/t/mix-install-in-umbrella-projects-without-mix-exs/9307" class="inline-onebox" rel="nofollow">Mix install in umbrella projects without mix.exs?</a>)</p>
<p>Then we’ll get huge boost on build time for unrelated changes. For example, if you change a mix file to add an option… boom! docker cannot use cache.</p>
<p>Also it’s very cumbersome as you need to add all mix files from all apps in umbrella project. You have 10 umlbreea apps? Then you need to have 10 <code>COPY</code> command to copy all mix files into the right place.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="133724" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/multi-stage-docker-image-for-phoenix/23427/26">Post #25</a>
	                </div>
	            </div>
              <div id="likers-container-133724" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="133724"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #25"></div>
  </section>
</div>
    <div class="postbit" id="133804" data-post-id="133804">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="egze" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/egze/120/13522_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  egze
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>If anyone is interested, here is my latest Docker setup. I hardcoded everything for development. For production I will probably do it differently and build a release. But for development it works just great.</p>
<p><code>docker/dev/Dockerfile</code></p>
<pre data-code-wrap="elixir"><code class="lang-elixir">FROM node:12.4-alpine as webpack

RUN npm install -g yarn

WORKDIR /app/assets

COPY assets/package.json assets/*yarn* ./

RUN apk --update --upgrade add ca-certificates build-base bash \
    &amp;&amp; update-ca-certificates --fresh \
    &amp;&amp; rm -rf /var/cache/apk/*  \
    &amp;&amp; yarn install \
    &amp;&amp; apk del build-base

COPY assets .

ENV NODE_ENV="development"

CMD ["tail", "-f", "/dev/null"]

###############################

FROM elixir:1.8-otp-22-alpine as app

WORKDIR /app

RUN apk --update --upgrade add ca-certificates inotify-tools postgresql-client bash \
    &amp;&amp; update-ca-certificates --fresh \
    &amp;&amp; rm -rf /var/cache/apk/*

COPY ./docker/dev/wait-for-postgres.sh /
COPY mix.* ./

ENV MIX_ENV="dev" \
    MIX_HOME=/opt/mix \
    HEX_HOME=/opt/hex

RUN mix local.hex --force \
    &amp;&amp; mix local.rebar --force \
    &amp;&amp; mix deps.get \
    &amp;&amp; mix deps.compile

CMD ["tail", "-f", "/dev/null"]

</code></pre>
<p><code>docker-compose.yml</code></p>
<pre data-code-wrap="elixir"><code class="lang-elixir">version: '3.7'

services:
  postgres:
    image: postgres:11-alpine
    container_name: project_postgres
    restart: always
    ports:
      - 15432:5432
    volumes:
      - ./docker/data/postgres:/var/lib/postgresql/data

  webpack:
    build:
      context: .
      dockerfile: ./docker/dev/Dockerfile
      target: "webpack"
    container_name: project_webpack
    restart: unless-stopped
    command: yarn run watch
    volumes:
      - .:/app
      - static:/app/priv/static

  app:
    build:
      context: .
      dockerfile: ./docker/dev/Dockerfile
      target: "app"
    container_name: project_app
    ports:
      - 4000:4000
    command: tail -f /dev/null
    volumes:
      - .:/app
      - static:/app/priv/static
      - deps:/app/deps
      - build:/app/_build
    depends_on:
      - postgres
      - webpack

volumes:
  static: {}
  deps: {}
  build: {}

</code></pre>
<p><code>docker/dev/wait-for-postgres.sh</code></p>
<pre data-code-wrap="elixir"><code class="lang-elixir">#!/bin/bash
# wait-for-postgres.sh

set -e

host="$1"
shift
cmd="$@"

until PGPASSWORD=$POSTGRES_PASSWORD psql -h "$host" -U "postgres" -c '\q'; do
  &gt;&amp;2 echo "Postgres is unavailable - sleeping"
  sleep 1
done

&gt;&amp;2 echo "Postgres is up - executing command"
exec $cmd
</code></pre>
<p>And <code>Makefile</code></p>
<pre data-code-wrap="elixir"><code class="lang-elixir">.PHONY: app server console sh clean

app:
	docker-compose up --detach --build app

setup: app
	docker-compose exec app /wait-for-postgres.sh postgres mix ecto.setup

server: setup
	docker-compose exec app mix phx.server

console: setup
	docker-compose exec app iex -S mix

sh: setup
	docker-compose exec app bash

clean:
	docker-compose down

</code></pre>
<p>Now I can just execute <code>make console</code> or <code>make server</code> and it will start all services and even wait for postgres to be healthy and execute migrations before starting the server on iex.</p>
<p>Thanks <a class="mention" href="/u/cnck1387" rel="nofollow">@cnck1387</a> for the helpful tips.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="133804" data-batch-url="/posts/batch_likers">
                        4
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/multi-stage-docker-image-for-phoenix/23427/27">Post #26</a>
	                </div>
	            </div>
              <div id="likers-container-133804" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="133804"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #26"></div>
  </section>
</div>
    <div class="postbit" id="135068" data-post-id="135068">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="nicbet" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/nicbet/120/28763_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  nicbet
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>FWIW, I’ve captured a quick tutorial on minimal (Alpine) Multi-Stage Docker image builds with Elixir 1.9 and Phoenix in this Gist: <a href="https://gist.github.com/nicbet/102f16359828405ce34ca083976986e1" class="inline-onebox" rel="noopener nofollow ugc">Elixir 1.9 Releases Alpine Linux Docker Multi-Stage Build · GitHub</a></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="135068" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/multi-stage-docker-image-for-phoenix/23427/28">Post #27</a>
	                </div>
	            </div>
              <div id="likers-container-135068" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="135068"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #27"></div>
  </section>
</div>
    <div class="postbit" id="161417" data-post-id="161417">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tme_317" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tme_317
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="cnck1387" data-post="25" data-topic="23427">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/c/2bfe46/48.png" class="avatar"> cnck1387:</div>
<blockquote>
<p>It took a while to wire all of that together, but now that it works, it’s really nice. It’s a setup that will work in both dev and prod using the same <code>docker-compose.yml</code> file</p>
</blockquote>
</aside>
<p>Hi <a class="mention" href="/u/cnck1387" rel="nofollow">@cnck1387</a>,</p>
<p>I was wondering if you have these dockerfiles and compose files open sourced?  I’ve read many blog posts with slightly different approaches and just not sure how to tie it all together for a basic generated phoenix umbrella app (with ecto).  I’m trying to get a development environment (editing using vscode remote container plugin) and a mix release driven multi-stage build delivering the .tar.gz release ready for deployment in a container in the same project.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="161417" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/multi-stage-docker-image-for-phoenix/23427/29">Post #28</a>
	                </div>
	            </div>
              <div id="likers-container-161417" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="161417"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-last-post cat-last-post" title="Last post!"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <span class="all-loaded">— All posts loaded —</span>
</div></template></turbo-stream>