If I were to use HAProxy instead of nginx, would it simply be making a docker-compose file, like at Step 8, but configure a HAProxy Docker instance instead in the docker-compose.yml?

I already have an ansible playbook that deploys HAProxy and I’m in the middle of adding the deployment of letsencrypt on it. So would it be possible to skip Step 8 in this guide and separately install HAProxy with ansible? Would the backend still communicate with the ansible-deployed HAProxy?

I don’t really know much about Ansible but I would suspect that it either installs HAProxy to your local machine or to some kind of container/VM like Docker. Either way, you wouldn’t use the Docker network to connect your containers together since your HAProxy install wouldn’t be inside Docker. In that case, skip step 8 since you won’t need NGINX at all. Instead, check out the second note in step 6 about exposing the ports of your server container to the local host (the computer which is running Docker). Check out the Docker Compose docs here: https://docs.docker.com/compose/compose-file/#ports and use the ports: ... line in your compose file to expose the Phoenix server port to your local host. Then, you can use HAProxy to proxy port 80 traffic from the correct domain to your internal port that you exposed with Docker Compose (just like NGINX was doing).

I don’t know much about Ansible or HAProxy but I’m sure the above solution would work. Let me know if that makes sense

ok I’m at step 9. I skipped step 8 because I’m not using nginx(see above). I also removed all ‘nginx-network’ references because the exposure to the outside world will be managed by HAProxy. Anyway I do:

docker-compose up

and the first time it ran it build alpine linux + erlang but at the build admin phase there seems to be a file missing. Any suggestions? where is this path? it’s not on the build machine(my mac). when I do docker container ls I get zero items.

Here is the log of the original run. I noticed that the network created is “kjvrvgphx_default” which is not the name of the app (kjvrvg). Not sure if this could be the issue. After this run, I commented-out all references to ngnx-network in the docker-compose file. I’m still confused WHERE this missing file path is. There are no containers running or cached as far as I can tell.

Yes, that helped thanks and I got the release built … with webpack too!

So now I have a release but no network so does that still mean that kjvrvg-server got deployed like the section below? even though I commented-out nginx-network? All I have to do is link up my HAProxy?

@jswny, I found myself using Swarm cluster with apps running as services. You can have Swarm cluster with 1 machine.
In Swarm this configuration will allow you to restart your application container without nginx or start nginx before your applications:

That’s pretty cool, I’ll have to check out Swarm. I admit it has been on my radar but I haven’t had time to look into it yet You can actually leave NGINX running when you restart you services, but it might spam your logs with service unavailable stuff.

Yeah for the IP address I’m sure you can just use localhost or 127.0.0.1 and then the port like you have since the IP is just your local machine and the correct port.

The point of the nginx-network is not even specific to NGINX itself, it’s actually just to have a Docker network setup so that the services can communicate with each other. I just named it nginx-network since instead of being specific to a certain app that you have deployed, it is the overall network for all of your apps since NGINX needs to communicate with all of them, so you have to have all of the apps on the same network. I think as long as your database container and app container are on the same Docker network it won’t matter what the network is called. The app container just needs to be able to communicate with the database container. Then, like I said you expose the app container’s server port to the outside world (your local machine) for HAProxy to send traffic to.

What Elixir code does LayoutView.webpack_css_path/2 contain? The first couple of webpack/Phoenix guides I found seem to assume that the Mix module is available to conditionally link to hot-reloaded CSS/JS, but, if I understand correctly, this won’t be the case if the app is running as a release built by Distillery, as I believe you’re finding.

If that’s the case, can you simplify LayoutView.webpack_css_path/2 so that it always outputs ‘/css/styles.css’ or whatever, without using Mix? (And the same for the JS function.)

I haven’t used webpack myself yet, and it’s entirely possible my post is misguided/wrong. If anyone has a link to a guide on replacing brunch with the latest version of webpack in Phoenix that works with releases, that would be great.

Like @BrightEyesDavid said, you can’t really use Mix in prod since it isn’t included in the release. So, what you should do is have Webpack build to the priv directory in your app’s root directory (like how the default Brunch build process works). Then, Distillery will package up your priv directory with your release, which you can then access in your code with priv_dir = Application.app_dir(:myapp, "priv"). You should probably then try rewriting that LayoutView.webpack_css_path/2 to pull from the built files in the priv directory.

def webpack_js_path(conn, path) do
if Mix.env == :dev do
static_path(conn, path)
else
"//localhost:8080#{path}"
end
end
def webpack_css_path(conn, path) do
if Mix.env == :dev do
static_path(conn, path)
else
""
end
end

so this is a little busted I guess, I will remove the Mix.env references, the whole if-structure and just unconditionally do:"//localhost:8080/css/app.css"
and"//localhost:8080/js/app.js"

Michael

~~ UPDATE ~~

So I did the above and phoenix is up and running(!), not getting the error anymore, but I think I broke css/webpack since the page is rendering completely unstyled. would it be the //localhost:8080/css/app.css path syntax? I feel this is a rigid hack.
here is what layout_view.ex looks like now:

defmodule KjvrvgWeb.LayoutView do
use KjvrvgWeb, :view
def webpack_js_path(conn, path) do
"//localhost:8080/js/app.js"
end
def webpack_css_path(conn, path) do
"//localhost:8080//css/app.css"
end
end

I’m not sure if I fully understand your post, but if this is for a release in production, I don’t think you want localhost:8080. My understanding is that that’s the webpack dev server, for hot reloading of assets during development.