2023-06-06
Also we'll be using the Plug module to keep things simple. This module is at the heart of popular Elixir web frameworks such as Phoenix.
Plug lives at the heart of Phoenix's HTTP layer, and Phoenix puts Plug front and center.
First, we need Podman so head on over to the official instllation instructions and then come back.
Next we need an image that we can install Elixir on.. I'll use Alpine Linux.
podman search alpine --filter is-official
Go ahead and pull it:
podman image pull docker.io/library/alpine
Check that it installed:
podman image list alpine
Now run it (more networking options here):
# -p host-port:container-port
podman run -dit --name alp --network=bridge -p 7070:7070 alpine /bin/ash
Make sure the container is running first:
podman ps
If you don't see any output then you must start the container:
podman start alp
Attach to container:
podman attach alp
You should now be logged in as root (don't worry this root can't do harm outside of the container)
Add a user that has sudo (inside the container):
adduser alpine
# enter a password for this user
# you could also change root's password with this command: passwd
Install the sudo program:
apk add sudo
Use visudo to allow the group wheel to use sudo:
visudo
# uncomment the line
# %wheel ALL=(ALL:ALL) ALL
You'll need to know a few vim commands to use visudo. If you really don't know then search up a quick tutorial. Hey you might end up liking vim.
Now add the new user to the wheel group:
adduser alp wheel && su alp
You should be the alp user now and not root.
Install Elixir:
sudo apk add elixir && cd ~
mix new myapp --sup
We'll now install the Plug dependency:
Edit mix.ex
vi mix.ex
# and make sure deps has plug as shown below
defp deps do
[
{:plug, "~> 1.14"},
{:plug_cowboy, "~> 2.0"}
]
end
Now install plug:
mix deps.get
# You'll be asked to install hex. Type Y
Great!
Now let's make the app fault tolerant by having the application supervise it:
Edit lib/myapp/application.ex
def start(_type, _args) do
children = [
{Plug.Cowboy, scheme: :http, plug: Myapp, options: [port: 7070]}
]
Lastly we'll add a router to the web app, Edit lib/myapp.ex
defmodule Myapp do
use Plug.Router
# matches a route
plug :match
# then forwards it to a dispatch
plug :dispatch
get "/" do
send_resp(conn, 200, "homepage")
end
get "/hello/:name" do
send_resp(conn, 200, "Hi #{name}")
end
# 404
get _ do
send_resp(conn, 404, "404 not found")
end
end
Start it up:
mix run --no-halt
Open up your browser and head over to localhost:7070/hello/world
Now we should compile the web app into a binary and also create an image from the container to make it portable.
First let's compile the code.
In the container's terminal run:
MIX_ENV=prod
RELEASE_NAME=myapp
mix release.init
compile:
mix release
You should now have a binary located at:
_build/dev/rel/myapp/bin/myapp
You can run it as so:
_build/dev/rel/myapp/bin/myapp start
We can now exit the container so that we can build an image with this binary installed.
exit && exit
In your host terminal run:
podman commit alp alp:v2
Now we can start up the new container with the binary running by default:
podman run -dit --network=bridge -p 7070:7070 --name alp2 alp:v2 /home/alpine/myapp/_build/dev/rel/myapp/bin/myapp start
The main benefits of using Podman over Docker are security related. I won't rehash it all here so if you want to learn more check out linode's explanation.
I suggest learning more about plug and its router from elixirschool.