Skip to content
This repository has been archived by the owner on Aug 27, 2020. It is now read-only.
/ pwr2-docker Public archive

ARCHIVED: Docker image based on Ubuntu with Elixir and Phoenix Framework integrated with Webpack+Relay+React

License

Notifications You must be signed in to change notification settings

iporaitech/pwr2-docker

Repository files navigation

Phoenix, Webpack, React and Relay (pwr2)

Docker image based on Ubuntu providing a base setup for a Phoenix+Webpack+Relay+React project, with some sugar and conventions to develop and build your own web applications.

You can also use this project without docker. See #49 for more info

We will improve docs and code including test coverage in the next releases

NOTICE: The default branch for this repo is develop. Check the README on master to see what's in the last release.

What is this for?

You can use this to start/learn/critic an Elixir Umbrella project with a core child Phoenix app acting as the web endpoint for core stuff and forwarding requests to /star-wars from its router to a Star Wars example app, also a Phoenix app under the same umbrella.

The core also provides the base assets used for other umbrella children as well as functionality to build (via Webpack) assets for other children apps.

So far we've implemented the following:

  • A GraphQL endpoint implemented in Elixir with Absinthe.
  • Authentication using JWTs (JSON Web Tokens) via GraphQL (LoginMutation & LogoutMutation).
  • Hardcoded Role based Authorization.
  • StarWars GraphQL example as core's sibling Phoenix app.
  • GraphiQL console.
  • Some interesting React/Relay components in the client(browser), including a router.
  • CSS Modules integration with Material Design Lite, now extracted to react-to-mdl.
  • Testing framework for the backend (Elixir/Phoenix).
  • Docs where you can find additional information about this project.

Umbrella Architecture

This whole Umbrella Architecture section is a WIP.

The workflow and "lifecycle"

  1. Create umbrella
  2. Create Core Phoenix app inside umbrella, run it on HTTP_PORT making sure everything works.
  3. Turn off Core.
  4. Create StarWars app inside umbrella, run it also on HTTP_PORT making sure everything works.
  5. Turn off StarWars.
  6. Configure Core.Mixfile to depend on {​:star_wars, ​in_umbrella:​ true}.
  7. Configure Core.Router to forward "/star-wars", StarWars.Router.
  8. Don't start StarWars.Endpoint. Comment it out in lib/star_wars.ex.
  9. Create core/webpack.umbrella.config.js containing instructions to build one commons bundle and one bundle for each app in the umbrella.
  10. Define a script in core/package.json to start Webpack using webpack.umbrella.config to build & watch the assets in dev.
  11. Adjust watchers in core/config/dev.exs.
  12. Turn ON iex -S mix phoenix.server from the root of the umbrella making sure everything works.
  13. Analyse and REFACTOR to architecture. After applying principles like DRY, SRP and others, now every app in the umbrella is responsible for a particular domain.

About the front-end Architecture

  • Apps outside umbrella.
  • Apps inside umbrella running simultaneously.
  • Apps using its own Phoenix page layout and bundle.
  • Apps using page layout from a sibling
  • Other scenarios

Also talk about yarn

Requirements

To run this software you need to install Docker on your system. It is very simple and there are a lot of guides and tutorials out there on the Internet.

NOTICE: this was only tested in Unix like OS (Mac OS X and Ubuntu) but it should run on Windows without major problems.

Usage Instructions

With Docker working on localhost, you can setup this project in 2 ways:

  1. Setup cloning this GitHub repo and build the image.
  2. Setup pulling Docker image from Docker Cloud repository.

With all setup, you can start the corresponding containers (aka services) by running the following command in your console:

docker-compose up

you can also just use the docker-compose.dev.example.yml file directly.

docker-compose -f docker-compose.dev.example.yml up

add -d to the above commands if you want them to execute in background

When the containers are all up and running, you can go inside the web app container and start the web app so you can play with it. To go inside the container execute the following command in the root directory of the project:

Assuming the files are placed in a directory named pwr2-docker and the generated container is named pwr2docker_web_1

docker exec -it pwr2docker_web_1 bash

You can see the names of running containers with the command docker ps on your localhost

Once inside the container, you'll need to switch to app user in order to execute Elixir/Phoenix commands. To switch to app user run:

su app

All the stuff in /home/app belongs to app user. You might experience some errors if you try to execute Elixir commands as root. Take a look at the Dockerfile to see how all the stuff is installed

Once switched to app user and in the APP_HOME directory, you can:

  1. Create and migrate dev database: mix do ecto.create, ecto.migrate
  2. Create and migrate test database: MIX_ENV=test mix do ecto.create, ecto.migrate
  3. Run db seeds to create a superadmin dev user: mix run apps/webapp/priv/repo/seeds.exs. Take a look at the seeds file to get the corresponding credentials.
  4. Start the application server: mix phoenix.server, or if you want to start the server in a Elixir console iex -S mix phoenix.server

Now you're ready to start making requests to the web app on the port you specified and try out some examples.

Testing

  1. Run all tests MIX_ENV=test mix espec --trace.
  2. Run tests while coding, for example, to run a specfic spec: mix test.watch spec/models/user_spec.exs --trace --focus.

Check ESpec, ESpec.Phoenix and mix test.watch to see more info about the testing framework used in this project.

Stopping containers

Execute docker-compose stop in the same directory where you started them with docker-compose up ....

If you want to stop them when running in foreground just press CTRL+C once.

Setup cloning this GitHub repo and building the image

  1. Clone the project to your localhost (you might want to fork it to your account before)
  2. Copy the docker-compose.dev.example.yml to docker-compose.yml and adjust the ports and volumes.
  3. Build the image. In the root directory of the project execute docker build .
  4. When the build finishes, tag the image to match the web image defined in your docker-compose file. For example docker tag IMAGE_ID pwr2:latest

Now you're ready to start the containers and try some stuff.

Setup pulling Docker image from Docker Cloud repository

  1. Open you console or terminal and execute docker login. You might not need this.
  2. Pull the image from Docker Cloud. Execute docker pull iporaitech/pwr2-docker:latest. You can also search for other tags besides latest.
  3. Copy the docker-compose.dev.example.yml to docker-compose.yml on your localhost and adjust the ports, volumes and image in web section to match the image tag you pulled in the step above.

Now you're ready to start the containers and try some stuff.

Once the containers are up and running you can copy the source code of the base project from the container to your localhost with the following command:

rsync -rav -e "ssh -p2224 -i insecure_key" --exclude "_build" --exclude "deps" root@localhost:/home/app/webapp/* .

Assuming you exposed the port 2224 to access the container via SSH

Notice: Tags/Releases in this GitHub repo are the equivalent to tags in the Docker Cloud repository, master is the latest image in DockerHub.

Examples

Once all setup and with the app running and assuming your HTTP_PORT is 4000, you can:

  1. Login with credentials available in priv/repo/seeds.exs. Logout is also available.
  2. Visit http://localhost:4000/admin/graphiql to access a GraphiQL IDE.
  3. Visit http://localhost:4000/admin/star-wars to experiment with our implementation of the Relay Star Wars example. The database for this example is implemented as an Elixir.Agent
  4. You can also use something like Google Chrome's Advanced Rest Client(ARC) or any other JSON API client and (with the corresponding Authorization header) send queries to http://localhost:4000/graphql like:
{
  "query": "query GetFactions($names:[String]){factions(names: $names) {id name}}",
  "variables": {
    "names": ["Galactic Empire", "Alliance to Restore the Republic"]
  }
}

About the technology stack

Basically, the stack is composed of server application and a Javascript client rendered in the browser.

Following a brief description of major components of this technology stack. See also the Dockerfile.

Baseimage-docker

A minimal Ubuntu base image modified for Docker-friendliness. This is the base Ubuntu image for this images (see FROM in the Dockerfile). It provides a correct init process, syslog-ng, logrotate among other stuff needed in most server installations.

Current: phusion/baseimage:0.9.19

Erlang/OTP

Erlang is a programming language used to build massively scalable soft real-time systems with requirements on high availability. Some of its uses are in telecoms, banking, e-commerce, computer telephony and instant messaging. Erlang's runtime system has built-in support for concurrency, distribution and fault tolerance.

This provides the Virtual Machine(VM) on top of which Elixir and Phoenix run

Current: Erlang/OTP 19.0

Elixir

Elixir is a dynamic, functional language designed for building scalable and maintainable applications.

Elixir leverages the Erlang VM, known for running low-latency, distributed and fault-tolerant systems, while also being successfully used in web development and the embedded software domain.

Current: Elixir 1.3.1

Phoenix

A productive web framework that does not compromise speed and maintainability.

Phoenix leverages the Erlang VM ability to handle millions of connections alongside Elixir's beautiful syntax and productive tooling for building fault-tolerant systems.

We use Phoenix as our backend programming framework

See mix.exs to check current version.

Absinthe

GraphQL implementation for Elixir, specifically using the packages Absinthe.Relay and Absinthe.Plug.

See mix.exs to check current versions.

Also, you might want to checkout the Relay GraphQL specifications to write GraphQL schemas to support Relay apps:

Node

Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient. Node.js' package ecosystem, npm, is the largest ecosystem of open source libraries in the world.

Phoenix relies on Node to compile and handle static assets.

Take a look at package.json to see all NPM packages used in this application.

Current: Node v6.3.1

Webpack

webpack is a module bundler. webpack takes modules with dependencies and generates static assets representing those modules.

We use this instead of brunch.io , which is the default to compile static assets in Phoenix

Take a look at webpack.config.js to see how the loaders and plugins are configured to make things work in the front-end.

See package.json to see the current versions of these NPM packages.

Relay & React

Relay is a Javascript framework for building data-driven React applications.

React is a Javascript library for building user interfaces.

See package.json to see the current versions of these dependencies and other NPM packages in this project.

Base Phoenix+Webpack project

Check mix.exs and mix.lock to know Elixir dependencies and package.json to know about Javascript dependencies.

How it was created

Inside the container in APP_HOME directory with command mix phoenix.new --no-brunch.

Later on, we've added Webpack and its Babel stuff; loader, presets, polyfill and runtime.

Take a look at config/dev.exs to see how we've configured a watcher for npm start, this is how you get live reloading when editing files.

About Docker Volumes

Although getting better in each release, we still find Docker for Mac volumes to be very slow. That's why we commented out the volumes configuration in the web section in the docker-compose.dev.example.yml file. Obviously, this is not a problem when running Docker on Linux.

Instead of mounting a volume to work with source code on the container we use Atom IDE with the remote-sync plugin. When this plugin is enabled everytime you save a file it gets automatically copied to the container via SSH. Probably, you might find similar or better strategies with your IDE or you local setup.

If you want to try volumes when running the image pulled directly from Docker Cloud, remember to first get the source code of this project into your localhost in the directory you want to share with the container. This is because the volumes are mounted from host to container (HOST:CONTAINER in the volumes definition in the docker-compose file). If the file don't exist in your localhost when mounting a dir they won't exist in your container in the specified directory even if they did exist in the image.

Issues and Contributing

See CONTRIBUTING.md.

Anyways, just create an issue if you have any question or want something but don't know exactly what it is.

Core Maintainers

With love from Iporaitech, a small startup based in Paraguay.

License

This project is licensed under MIT.

About

ARCHIVED: Docker image based on Ubuntu with Elixir and Phoenix Framework integrated with Webpack+Relay+React

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •