From 94f1585d7631fea156b76c1fb1f56dbfd616223e Mon Sep 17 00:00:00 2001 From: Exadra37 Date: Tue, 30 Apr 2019 21:39:17 +0100 Subject: [PATCH] Upgraded to an Elixir Docker Stack, including Postgres support. Signed-off-by: Exadra37 --- .gitignore | 3 + AUTHOR.md | 1 - CONTRIBUTING.md | 62 +- CONTRIBUTORS.md | 1 - README.md | 753 +++++++- bin/elixir | 1687 +++++++++++++++++ bin/erl | 1 + bin/iex | 1 + bin/mix | 1 + bin/test-sudo | 26 + docker/build/alpine.Dockerfile | 135 ++ docker/build/debian.Dockerfile | 95 + docker/build/debian.esl.Dockerfile | 119 ++ docker/build/debian.git.branch.Dockerfile | 159 ++ docker/build/debian.git.release.Dockerfile | 161 ++ docker/build/debian.slim.Dockerfile | 97 + docker/build/observer-debian.Dockerfile | 61 + .../custom-ssl/certificates/.gitignore | 2 + .../android/adb-setup-certificate.sh | 29 + .../browsers/add-certificate-to-browser.sh | 59 + .../nodejs/add-certificate-to-server.sh | 49 + .../add-custom-authority-certificate.sh | 35 + .../operating-system/config/localhost.txt | 15 + .../operating-system/config/openssl.cnf | 353 ++++ ...te-and-add-self-signed-root-certificate.sh | 73 + .../create-self-signed-domain-certificate.sh | 112 ++ .../resources/scripts/create-workspace-dir.sh | 23 + .../scripts/debian/install-firefox.sh | 16 + .../scripts/debian/install-inotify-tools.sh | 16 + .../scripts/debian/install-locales.sh | 25 + .../scripts/debian/install-nodejs.sh | 23 + .../resources/scripts/debian/install-pgcli.sh | 17 + .../scripts/debian/install-postgres.sh | 50 + .../scripts/debian/install-sublime-text.sh | 106 ++ .../debian/install-visual-studio-code.sh | 37 + .../scripts/debian/remove-build-deps.sh | 53 + .../scripts/elixir/bin/elixir-server | 31 + .../resources/scripts/elixir/bin/observer | 64 + .../resources/scripts/elixir/bin/observer-cli | 63 + .../elixir/observer/fix-dependencies.sh | 96 + .../scripts/elixir/phoenix/install.sh | 39 + .../resources/scripts/install-oh-my-zsh.sh | 32 + .../build/resources/scripts/setup-postgres.sh | 31 + .../scripts/show-hostname-ip-address.sh | 21 + .../User/Package Control.sublime-settings | 13 + .../User/Preferences.sublime-settings | 18 + .../Packages/User/LSP.sublime-settings | 32 + .../language-server-protocol/bin/elixir-ls | 14 + .../language-server-protocol/install.sh | 56 + .../resources/scripts/sublime-text-3/setup.sh | 34 + docs/demos/elixir-hello-world.md | 7 - docs/how-to/create_a_merge_request.md | 14 - docs/how-to/create_an_issue.md | 45 - docs/how-to/create_branches.md | 54 - docs/how-to/install.md | 9 - docs/how-to/uninstall.md | 9 - docs/how-to/use.md | 9 - docs/the-package/what_is_it.md | 10 - docs/the-package/when_to_use_it.md | 9 - docs/the-package/why_exists.md | 10 - src/bin/elixir | 34 - src/build/1.4/Dockerfile | 39 - 62 files changed, 4950 insertions(+), 299 deletions(-) create mode 100644 .gitignore create mode 100755 bin/elixir create mode 120000 bin/erl create mode 120000 bin/iex create mode 120000 bin/mix create mode 100755 bin/test-sudo create mode 100644 docker/build/alpine.Dockerfile create mode 100644 docker/build/debian.Dockerfile create mode 100644 docker/build/debian.esl.Dockerfile create mode 100644 docker/build/debian.git.branch.Dockerfile create mode 100644 docker/build/debian.git.release.Dockerfile create mode 100644 docker/build/debian.slim.Dockerfile create mode 100644 docker/build/observer-debian.Dockerfile create mode 100644 docker/build/resources/custom-ssl/certificates/.gitignore create mode 100755 docker/build/resources/custom-ssl/trusted-store/android/adb-setup-certificate.sh create mode 100755 docker/build/resources/custom-ssl/trusted-store/browsers/add-certificate-to-browser.sh create mode 100755 docker/build/resources/custom-ssl/trusted-store/nodejs/add-certificate-to-server.sh create mode 100755 docker/build/resources/custom-ssl/trusted-store/operating-system/add-custom-authority-certificate.sh create mode 100644 docker/build/resources/custom-ssl/trusted-store/operating-system/config/localhost.txt create mode 100644 docker/build/resources/custom-ssl/trusted-store/operating-system/config/openssl.cnf create mode 100755 docker/build/resources/custom-ssl/trusted-store/operating-system/create-and-add-self-signed-root-certificate.sh create mode 100755 docker/build/resources/custom-ssl/trusted-store/operating-system/create-self-signed-domain-certificate.sh create mode 100755 docker/build/resources/scripts/create-workspace-dir.sh create mode 100755 docker/build/resources/scripts/debian/install-firefox.sh create mode 100755 docker/build/resources/scripts/debian/install-inotify-tools.sh create mode 100755 docker/build/resources/scripts/debian/install-locales.sh create mode 100755 docker/build/resources/scripts/debian/install-nodejs.sh create mode 100755 docker/build/resources/scripts/debian/install-pgcli.sh create mode 100755 docker/build/resources/scripts/debian/install-postgres.sh create mode 100755 docker/build/resources/scripts/debian/install-sublime-text.sh create mode 100755 docker/build/resources/scripts/debian/install-visual-studio-code.sh create mode 100755 docker/build/resources/scripts/debian/remove-build-deps.sh create mode 100755 docker/build/resources/scripts/elixir/bin/elixir-server create mode 100755 docker/build/resources/scripts/elixir/bin/observer create mode 100755 docker/build/resources/scripts/elixir/bin/observer-cli create mode 100755 docker/build/resources/scripts/elixir/observer/fix-dependencies.sh create mode 100755 docker/build/resources/scripts/elixir/phoenix/install.sh create mode 100755 docker/build/resources/scripts/install-oh-my-zsh.sh create mode 100755 docker/build/resources/scripts/setup-postgres.sh create mode 100755 docker/build/resources/scripts/show-hostname-ip-address.sh create mode 100644 docker/build/resources/scripts/sublime-text-3/elixir/.config/sublime-text-3/Packages/User/Package Control.sublime-settings create mode 100644 docker/build/resources/scripts/sublime-text-3/elixir/.config/sublime-text-3/Packages/User/Preferences.sublime-settings create mode 100644 docker/build/resources/scripts/sublime-text-3/elixir/language-server-protocol/.config/sublime-text-3/Packages/User/LSP.sublime-settings create mode 100755 docker/build/resources/scripts/sublime-text-3/elixir/language-server-protocol/bin/elixir-ls create mode 100755 docker/build/resources/scripts/sublime-text-3/elixir/language-server-protocol/install.sh create mode 100755 docker/build/resources/scripts/sublime-text-3/setup.sh delete mode 100644 docs/demos/elixir-hello-world.md delete mode 100644 docs/how-to/create_a_merge_request.md delete mode 100644 docs/how-to/create_an_issue.md delete mode 100644 docs/how-to/create_branches.md delete mode 100644 docs/how-to/install.md delete mode 100644 docs/how-to/uninstall.md delete mode 100644 docs/how-to/use.md delete mode 100644 docs/the-package/what_is_it.md delete mode 100644 docs/the-package/when_to_use_it.md delete mode 100644 docs/the-package/why_exists.md delete mode 100755 src/bin/elixir delete mode 100644 src/build/1.4/Dockerfile diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3e4ed78 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.Trash-1000/ +.local/ +.env diff --git a/AUTHOR.md b/AUTHOR.md index b1f3285..c290767 100644 --- a/AUTHOR.md +++ b/AUTHOR.md @@ -27,6 +27,5 @@ https://exadra37.com --- -[<< previous](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/docs/how-to/uninstall.md) | [next >>](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/CONTRIBUTORS.md) [HOME](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/README.md) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index baa3b97..5741b31 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,17 +5,16 @@ Contributions are welcome, provided that hey follow this guidelines. ## HOW TO CONTRIBUTE -### In a Current Issue -Browse the [current open issues](https://gitlab.com/exadra37-docker/elixir/elixir/issues) and participate in the -discussion for the ones you can help. +### With a new Issue +If you have a new issue to report, please create it [here](https://gitlab.com/exadra37-docker/elixir/elixir/issues/new) and please follow [this guidelines](#issues-guidelines). -### In a new Issue -If you have a new issue to report, please [create it](https://gitlab.com/exadra37-docker/elixir/elixir/issues/new) by -following the applicable [issue guidelines](docs/how-to/create_an_issue.md). +### In a Current Issue +Browse the [current open issues](https://gitlab.com/exadra37-docker/elixir/elixir/issues) and participate in the +discussion for the ones you can help. ### Solving an Issue @@ -28,8 +27,57 @@ Now is time to fork the repository and start coding on it. When you are ready to merge it, please proceed as per this [Merge Requests Guidelines](docs/how-to/create_a_merge_request.md). +## ISSUES GUIDELINES + +Always perform a search to see if your Issue as been already reported. + + +### Generic Guidelines + +Issues must use one of the available templates and all topics marked as required must be filled, by erasing the current +help and example info on them and write your own text. + +All optional topics not used must maintain their title and have their body replaced by 'N/A'. + +When any created issue do not follow this guidelines it will not be considered. + +Each issue will have is own Branch that are created as demonstrated [here](create_branches.md). + + +### Bug Fix / Security Fix + +Each issue should only target a specific bug or security flaw, unless they are tightly coupled to the point you can't +solve them separately. + +Create the issue [here](https://gitlab.com/exadra37-docker/elixir/elixir/issues/new) with the template +`bug_or_security_fix.md`. + + +### New Feature / Improve Feature / Refracting Code + +Starts with the [Creation of a Milestone](https://gitlab.com/exadra37-docker/elixir/elixir/milestones/new). + +Now we should split what we want to do in many tasks as we can by creating an Issue for each task and assign the issue +to the Milestone. + +Create each issue [here](https://gitlab.com/exadra37-docker/elixir/elixir/issues/new) using the relevant template: + +* `new_feature.md` +* `improve_feature.md` +* `refracting_code.md` +* `bug_or_security_fix.md` + + +## MERGE REQUEST GUIDELINES + +When opening your Merge Request ensure to do it against the `master` branch. + +Merge requests must use one of the available templates and all topics marked as `required` must be filled. + +All optional topics not used must maintain their title and have their body replaced by 'N/A'. + + --- -[<< previous](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/docs/how-to/use.md) | [next >>](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/docs/how-to/create_an_issue.md) [HOME](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/README.md) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 1c88911..9ad6d8f 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -3,6 +3,5 @@ Before you put your first Merge Request, please add your name to the end of the list: -[<< previous](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/AUTHOR.md) | [next >>](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/LICENSE) [HOME](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/README.md) diff --git a/README.md b/README.md index d590ae9..65a0b95 100644 --- a/README.md +++ b/README.md @@ -1,67 +1,738 @@ -# ELIXIR DOCKER IMAGE - - -## MENU - -* **The Package** - + [Why Exists?](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/docs/the-package/why_exists.md) - + [What Is It?](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/docs/the-package/what_is_it.md) - + [When To use It?](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/docs/the-package/when_to_use_it.md) -* **How To** - + [Install](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/docs/how-to/install.md) - + [Use](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/docs/how-to/use.md) - + [Report an Issue](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/docs/how-to/create_an_issue.md) - + [Create a Branch](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/docs/how-to/create_branches.md) - + [Open a Merge Request](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/docs/how-to/create_a_merge_request.md) - + [Uninstall](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/docs/how-to/uninstall.md) -* **Demos** - + [Elixir - Hello World](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/docs/demos/elixir-hello-world.md) -* **Road Map** +# ELIXIR DOCKER STACK + +The **Elixir Docker Stack** is a wrapper around the normal tools we use for +developing in Elixir, thus we can invoke `elixir`, `mix`, `iex` and other tools +without having them installed in our computer, and everything should work as if +they where normally installed, because throwaway docker containers will be +created to run this commands for us. + + +# MENU + +* **QUICK START** + + [Install](#install) + + [Creating a New Phoenix App](#creating-a-new-phoenix-app) + + [Creating a New App With a Specific Version of Elixir and Phoenix](#creating-a-new-app-with-a-specific-version-of-elixir-and-phoenix) +* **ELIXIR DOCKER STACK EXPLAINED** + + [Why Exists?](#why-exists) + + [What Is It?](#what-is-it) + + [What is Included?](#what-is-included) + + [What it does for us under the hood?](#what-it-does-for-us-under-the-hood) +* **HOW TO** + + [Install](#install) + + [Use](#how-to-use) + - [Elixir](#elixir) + - [Mix](#mix) + - [IEx](#iex) + - [Observer](#observer) + + [Graphical User Interface](#graphical-user-interface) + + [Htop](#htop) + + [Shell](#shell) + + [Contribute](./CONTRIBUTING.md) + - [Report an Issue](./CONTRIBUTING.md#with-a-new-issue) + - [Open a Merge Request](./CONTRIBUTING.md#merge-request-guidelines) + + [Uninstall](#uninstall) +* **ROAD MAP** + [Milestones](https://gitlab.com/exadra37-docker/elixir/elixir/milestones) + [Overview](https://gitlab.com/exadra37-docker/elixir/elixir/boards) -* **About** +* **ABOUT** + [Author](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/AUTHOR.md) + [Contributors](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/CONTRIBUTORS.md) - + [Contributing](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/CONTRIBUTING.md) + [License](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/LICENSE) -## SUPPORT DEVELOPMENT +# QUICK START -If this is useful for you, please: +## Install -* Share it on [Twitter](https://twitter.com/home?status=Base%20%23DockerImage%20for%20%23Elixir%20%23developers%20https%3A//gitlab.com/exadra37-docker/elixir/elixir%20by%20%40Exadra37.%20%23docker%20%23dockercontainers%20%23myelixirstatus) or in any other channel of your preference. -* Consider to [offer me](https://www.paypal.me/exadra37) a coffee, a beer, a dinner or any other treat 😎. +Clone the project somewhere in your computer: +```bash +git clone https://gitlab.com/exadra37-docker/elixir/elixir-docker-stack.git +``` -## EXPLICIT VERSIONING +Next we need to set where you have installed the **Elixir Docker Stack**: -This repository uses [Explicit Versioning](https://gitlab.com/exadra37-versioning/explicit-versioning) schema. +```bash +export ELIXIR_DOCKER_STACK_INSTALL_DIR="${PWD}/elixir-docker-stack" +``` +> **NOTE: The `export` command assumes you are not inside the folder `elixir-docker-stack`** + +And we also need to export to our `PATH`, the `bin` folder for the **Elixir Docker Stack**: + +```bash +export PATH="${ELIXIR_DOCKER_STACK_INSTALL_DIR}/bin:${PATH}" +``` +> **NOTE**: +> +> * If you already have Elixir installed, the `bin` folder for the **Elixir +> Docker Stack** will be the first in the `$PATH`, thus when you invoke +> `elixir`, `mix`, `iex`, `erl` or `rebar` you are not using the ones you +> already have installed, instead you are running the **Elixir Docker Stack** ones. +> + +Please bear in mind that once we are using `export` the **Elixir Docker Stack** +only works on this current shell session, if you open another window or tab you +need to repeat the `export` commands. + +For a **permanent installation** add to your shell the `export` commands. In a +bash shell the file to add them is located at `~/.bashrc`. + +Now is time to build the docker image for the **Elixir Docker Stack**: + +```bash +elixir build debian +``` + +Let's do some smoke tests: + +```bash +$ elixir --version +Erlang/OTP 21 [erts-10.3.4] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe] + +Elixir 1.8.1 (compiled with Erlang/OTP 21) + +$ mix phx.new --version +Phoenix v1.4.3 +``` + +Seems that we have a working **Elixir Docker Stack** :). + +[Menu](#menu) + + +## Creating a New Phoenix App + +Following along the official [Up and Running](https://hexdocs.pm/phoenix/up_and_running.html) for the Phoenix framework. + +Creating a new Phoenix app: + +```bash +mix phx.new hello +``` + +Now we need to get inside the directory for the `hello` app: + +```bash +cd hello +``` + +Let's create the database for the `hello` app: + +```bash +mix ecto.create +``` +> **NOTE**: Did you notice something different from your normal work-flow? + + +Time to start the Phoenix server: + +```bash +mix phx.server +``` + +The `hello` app is now running on http://localhost:4000. + +[Menu](#menu) + + +## Creating a New App With a Specific Version of Elixir and Phoenix + +Let's imagine that you want to quickly try an old app that is stuck on Elixir +version `1.4` and Phoenix version `1.3.4`, all you need to do is to... + +Let's imagine that you bought a book and discovered that the code examples on it +only work on Elixir `1.4` and Phoenix `1.3.4`, and instead of figuring out how +to make the code work for the current versions, you can quickly create a throwaway +docker stack for it: + +```bash +mix --elixir-version 1.4.5 --phoenix-version 1.3.4 phx.new myapp +``` + +Lets check that we have the new app working with the version we required for +Elixir: + +```bash +$ cd myapp && elixir --version +Erlang/OTP 19 [erts-8.3.5.7] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false] + +Elixir 1.4.5 +``` + +and for Phoenix the version is: + +```bash +mix phx.new --version +Phoenix v1.3.4 +``` + +If you are curious about the docker image we have created, check it with: + +```bash +$ sudo docker image ls | head -2 +REPOSITORY TAG IMAGE ID CREATED SIZE +exadra37/elixir-phoenix 1.4.5-1.3.4-debian 6fba76ed6d7c 5 minutes ago 969MB +``` + +Finally lets confirm that we have the defaults pinned: + +```bash +$ cat .elixir-docker-stack-defaults +elixir_version=1.4.5 +phoenix_version=1.3.4 +phoenix_command=phx.server +dockerfile=debian +database_image=postgres:11-alpine +database_user=postgres +database_data_dir=/home/exadra37/.elixir-docker-stack/Developer_Acme_Elixir_Phoenix_myapp/postgres/data +database_command=postgres +``` + +Now you can follow the same procedures of the `hello` app to have `myapp` up and +running on http://localhost:4000. + +[Menu](#menu) + + +## Getting Help + +To get help for the **Elixir Docker Stack** you must ask explicitly with an +argument passed to the help flag `-h stack`: + +```bash +$ elixir --help stack + +ELIXIR DOCKER STACK + +A docker developemnt stack that includes Elixir, Phoenix, Erlang, Oberver and Postgres. + + +ELIXIR CLI USAGE: + + elixir [options] [.exs file] [data] + + +ELIXIR DOCKER STACK USAGE: + + elixir [options] [command] [args] + + +ELIXIR DOCKER STACK OPTIONS: + + -d, --detached Run the docker container detached from the terminal. + + --db, --database Starts the container with the Postgres database up. + + --df, --dockerfile The dockerfile to run a container. + Defaults to: debian + $ elixir --dockerfile alpine up + $ elixir --dockerfile debian.slim up + + --ev, --elixir-version The Elixir version to be used for the docker tag, + Defaults to the latest Elixir version: 1.8 + $ elixir --elixir-version 1.3.4 up + + -h, --help Shows the help for the Elixir CLI and Stack. + $ elixir -h + $ elixir --help + $ elixir --help stack + + -it, --interactive-tty Run the docker container attached to the terminal. + $ elixir -it up + + --mix-env Sets the MIX_ENV var in the container. + Defaults to dev. + $ mix --mix-env test ecto.create + + -p, --publish Map the host ports to the docker container ports. + Defaults to: 4000:4000 . + $ elixir --publish 8000:4000 up + + --pv, --phoenix-version The Phoenix version to be installed. + Defaults to the last release, eg: 1.4.3 . + $ elixir --phoenix-version 1.3.4 up + + -u, --user The user we want to run inside the container, + Defaults to user, eg: elixir . + $ elixir --user root shell + + --verbose Enables verbose output for the docker stack. + Defaults to level 0, and can go until level 4. + $ elixir --verbose 1 up + $ elixir --verbose 2 shell + $ elixir --verbose 3 observer + $ elixir --verbose 4 build + + --wa, --wait-dummy-app Seconds to wait for the app dummy container to be ready. + Defaults to 1 second. + $ elixir --wait-dummy-app 3 up + + --wd, --wait-database Seconds to wait for the database is up and running. + Defaults to 5 seconds. + $ elixir --wait-database 10 new-database myapp_test + + +ELIXIR DOCKER STACK COMMANDS: + + Runs Elixir inside the container as it would in the host. + $ elixir --help + + build Builds the docker image for the given dodkerfile. + Defaults to build from: debian . + $ elixir build + $ elixir build alpine + + container-logs Shows a tail -f of the container logs. + $ elixir container-logs + + down Stops and removes the running container. + $ elixir down + + iex The Elixir IEx shell. + $ iex [options] + + mix The Elixir mix tool. + $ mix [options] + $ mix help + $ mix new elixir-project + $ mix phx.new phoenix-app + + new-database Creates a new database. + Defaults to the current folder name with suffix "_dev". + $ elixir new-database + $ elixir new-database acme + + pgcli A better shell for Postgres, includes auto-completion. + $ elixir pgcli [options] + + observer Starts the Observer GUI from an IEx shell. + $ elixir observer + + observer-cli Allows to start from IEx the Observer CLI(like Linux HTOP). + $ elixir observer-cli + + up Starts the Elixir docker stack. + $ elixir up + $ elixir --db up + $ elixir --dockerfile alpine up + $ elixir -it --publish 8000:4000 up + $ elixir --elixir-version 1.3 --phoenix-version 1.3.4 --db up + + shell A shell inside the container for the Elixir docker stack. + $ elixir shell + $ elixir -u root shell +``` + +So if we try to get help without using the argument `stack` for the help flag, +we get the usual output: + +```bash +$ elixir -h +Usage: elixir [options] [.exs file] [data] + + -e COMMAND Evaluates the given command (*) + -r FILE Requires the given files/patterns (*) + -S SCRIPT   Finds and executes the given script in PATH + -pr FILE Requires the given files/patterns in parallel (*) + -pa PATH Prepends the given path to Erlang code path (*) + -pz PATH Appends the given path to Erlang code path (*) + + --app APP Starts the given app and its dependencies (*) + --cookie COOKIE Sets a cookie for this distributed node + --detached Starts the Erlang VM detached from console + --erl SWITCHES Switches to be passed down to Erlang (*) + --help, -h Prints this message and exits + --hidden Makes a hidden node + --logger-otp-reports BOOL Enables or disables OTP reporting + --logger-sasl-reports BOOL Enables or disables SASL reporting + --name NAME Makes and assigns a name to the distributed node + --no-halt Does not halt the Erlang VM after execution + --sname NAME Makes and assigns a short name to the distributed node + --version, -v Prints Elixir version and exits + --werl Uses Erlang's Windows shell GUI (Windows only) + +** Options marked with (*) can be given more than once +** Options given after the .exs file or -- are passed down to the executed code +** Options can be passed to the Erlang runtime using ELIXIR_ERL_OPTIONS or --erl +``` + +The help for all the other tools included in the **Elixir Docker Stack** do not +have any special treatment and beahave exactly as you are used to. + +[Menu](#menu) + + +# ELIXIR DOCKER STACK EXPLAINED + +This section will try to answer some questions you may have regarding the +**Elixir Docker Stack**, and to explain how some details are handled for us, to +free up the developer from manually set them. + +## Why Exists? + +Initially was supposed to be only a simple docker image for Elixir with my +favourite shell and with a unprivileged user inside the docker container, but +end-up to grow up to be a full development stack for Elixir. + +I am a huge fan of using docker work-flow in development, and some of the +reasons for it are: + +* Same development environment across computers and developers working on the + same project. +* I can run as many versions as I want of the tools I use, and throw away them + when I am done, without impacting my operating system, and yes I know I can + use version managers to achieve the same. +* A cleaner operating system, once all my development tooling is running in + docker containers, thus I can upgrade my OS at any-time with less fuss. +* I can obtain a shell inside a docker container, install as many stuff I want + to try, without risking to mess-up, break the operating system, or leave + left-overs after I uninstall them(remember docker containers are destroy on + exit). +* More secure, once docker acts like a "sandbox", and yes I know that docker + have suffered from "sandbox" escape in the past. + +[Menu](#menu) + + +## What is It? +The **Elixir Docker Stack** is a set of tools needed for a normal development +work-flow with Elixir. -## BRANCHES +The goal is to be able to use this tools as if they are installed normally in +the operating system, or if the developer prefers to use them from a shell +inside the docker container. -Branches are created as demonstrated [here](docs/how-to/create_branches.md). +All docker containers created are ephemeral, thus they are destroyed when the +command we executed inside them returns. To keep state we map folders from the +host computer to inside the docker container. -This are the type of branches we can see at any moment in the repository: +[Menu](#menu) -* `master` - issues and milestones branches will be merged here. Don't use it in - production. -* `last-stable-release` - matches the last stable tag created. Useful for - automation tools. Doesn't guarantee backwards - compatibility. -* `4-fix-some-bug` - each issue will have is own branch for development. -* `milestone-12_add-some-new-feature` - all Milestone issues will start, tracked and merged - here. -Only `master` and `last-stable-release` branches will be permanent ones in the -repository and all other ones will be removed once they are merged. +## What is Included? +The software included: -## DISCLAIMER +* Elixir +* Phoenix +* Erlang +* Postgres + +The most useful tools included in the bin path: + +* elixir +* mix +* erl +* rebar +* rebar3 +* observer +* pgcli + +[Menu](#menu) + + +## What it does for us under the hood? + +When we run `mix phx.new hello` the **Elixir Docker Stack** will handle for +us some tasks, like creating the docker network, starting the database server, +pinning the defaults and updating the app configuration. + +[Menu](#menu) + +### Creation of a dedicated docker network + +The `hello` app will have a dedicated docker network, named `hello_network`, to +be used when communicating between the containers on the stack. + +```bash +$ sudo docker network ls | grep hello_network - +c78f64609b20 hello_network bridge local +``` + +[Menu](#menu) + +### Creation and setup of a dedicated docker container for the app database + +I have asked previously if you noticed something different in your work-flow for +when you need to run `ecto.create` after creating a new app, and if you have not +figured it out yet, is that with the **Elixir Docker Stack** you don't have +to manually start or ensure that you have a database up and running, because +this is done automatically for you. + +The `hello` app will have a dedicated container for the database, named +`hello_postgres`, that is created from the official docker image for Postgres. + +By default the database for this container will be persisted in host in the +directory `${host_setup_dir}_${new_app_name}/${database_engine}/data`, that may +translate to something like `~/.elixir-docker-stack/Developer_Acme_Elixir_Phoenix_hello/postgres/data`. + +Once we run the database in a dedicated container we need to ensure that the +`hello` app is able to communicate with it, and for that we need to adjust the +`hostname:` in `config/dev.exs` to point to `hello_postgres`, instead of the +default of `localhost`. In order to save us from having to do it manually, the +**Elixir Docker Stack** updates the `hello` app config for us: + +```bash +$ cat config/dev.exs | tail -8 + +# Configure your database +config :hello, Hello.Repo, + username: "postgres", + password: "postgres", + database: "hello_dev", + hostname: "hello_postgres", + pool_size: 10 +``` + +Now we have the `hostname:` entry updated from `localhost` to `hello_postgres`. + +Docker containers sharing the same network can communicate between them by using +the container name as a DNS resolver inside the network. So in this case we use +for the `hostname:` the value of `hello_postgres`, that is the name used for the +database container. + +[Menu](#menu) + +### Pinning the defaults + +Each time we run the **Elixir Docker Stack** for the `hello` app we want to +ensure that we do it exactly with the same defaults, so that we have parity in +the development work-flow across computers and developers. + +To achieve this we will use a the file named `.elixir-docker-stack-defaults` +in the root of the app project, that **MUST** be tracked in git. + +To save us from having to create this file manually, the **Elixir Docker Stack** +have created it for us when we created the `hello` app with `mix phx.new hello`. + +Let's take a look to what is inside the file: + +```bash +$ cat .elixir-docker-stack-defaults +elixir_version=1.8 +phoenix_version=1.4.3 +phoenix_command=phx.server +dockerfile=debian +database_image=postgres:11-alpine +database_user=postgres +database_data_dir=/home/exadra37/.elixir-docker-stack/Developer_Acme_Elixir_Phoenix_hello/postgres/data +database_command=postgres +``` + +As we can see we have pinned some defaults, and the most important ones are +`elixir_version`, that pins the docker image to be used by this app, and +`phoenix_version` that pins the Phoenix version. + +So this file guarantees that the **Elixir Docker Stack** always use the same +defaults for the `hello` App, unless we decide to override them on a command +invocation. + +[Menu](#menu) + + +# HOW TO USE + +## Elixir + +The elixir CLI tool will be used as you are used to, but it responds to some +additional options and commands, and you can all with examples by asking for +help: + +```bash +elixir --help stack +``` + +All this options and arguments are used to handle the docker stack and to make +some tasks easier for us. + +[Menu](#menu) + +## Mix + +The mix CLI tool works as usual but accepts some options that are specific to +the **Elixir Docker Stack**. + +[Menu](#menu) + +### The `--mix-env` option + +From the name should be pretty options what is for... + +Use it like: + +```bash +mix --mix-env test ecto.create +``` + +[Menu](#menu) + +### The `--pv, --phoenix-version` option + +When creating a new app with Mix, the latest Phoenix will be used, but we can +use this option to create the app with an older version of Phoenix. + +Use like this: + +```bash +mix --phoenix-version 1.3.4 php.new my_app_name +``` + +[Menu](#menu) + +### The `--ev, --elixir-version` option + +For the same reasons that we may want to use `--phoenix-version` we may also +want to specify the Elixir version to use, and for that we need to use the +`--elixir-version` option, that will be used to construct the tag to pull the +official docker image for Elixir. You can see all available tags in the +Docker Hub [Elixir repository](https://hub.docker.com/_/elixir?tab=tags). + +By default the **Elixir Docker Stack** defaults to a specific major version of +Elixir, eg: `1.8`, that is a full Debian release, that makes the docker images +substantially bigger then `1.8-slim` or `1.8-alpine` tags, but comes with the +build dependencies that are necessary for some dependencies, that need to use +`make` and build some C libraries. + +So if we need to create a new Phoenix app that uses the latest version available +for Elixir `1.7.*`, then we type: + +```bash +mix --elixir-version 1.7 phx.new my_app_name +``` + +or for a Slim Debian release: + +```bash +mix --elixir-version 1.7-slim phx.new my_app_name +``` + +But if you need to pin to the exact Elixir version, then: + +```bash +mix --elixir-version 1.7.1 phx.new my_app_name +``` + +[Menu](#menu) + +## IEx + +Just use as usual: + +```bash +iex +``` + +or + +```bash +iex -S mix +``` + +or any other command you are used to run... + +> **NOTE**: +> +> Observer is usually broken in Debian Slim or Alpine flavours. This is an +> issue that derives from the official docker image for Elixir, thus use only +> the default Debian docker image if you need to use Observe, or in +> alternative see the next section to use the custom command `elixir observer`. + +[Menu](#menu) + +## Observer + +Observer runs in a different docker image from our app, thus in order to use the +**Elixir Docker Stack** command to start the Observer you need to have already +the app up and running, otherwise a fatal error will be raised. + +[Menu](#menu) + +### Graphical User Interface + +To run it, just type: + +```bash +elixir observer +``` + +This command will fire up an `IEx` session and start the Observer for us, and +once it also connects us to the node where our App is running we just need to +select if from the `Nodes` menu. + +[Menu](#menu) + +### HTOP + +So if you already know HTOP for Linux, than you may have already an idea of +what is expecting you ;). + +To use this command the app needs to have installed the `{:observer_cli, "~> 1.4"}` +dependency. + +To run, just type: + +```bash +elixir observer htop +``` + +This command will fire up a session in the `IEx` shell for the app, and we just +need to type in the IEx shell: + +```bash +iex> :observer_cli.start +``` + +Enjoy your [HTOP](https://github.com/zhongwencool/observer_cli) for Elixir :) + +[Menu](#menu) + +### Shell + +As already mentioned the Observer run in a different container from our app, +thus if for some reason you need to access the bash shell for some debugging or +to fire up an IEx shell, you just need to run a bash shell in the Observer +container. + +Just type: + +```bash +elixir observer shell +``` + +or for root access: + +```bash +elixir --user root observer shell +``` + +[Menu](#menu) + + +# SUPPORT DEVELOPMENT + +If this is useful for you, please: + +* Share it on [Twitter](https://twitter.com/home?status=Base%20%23DockerImage%20for%20%23Elixir%20%23developers%20https%3A//gitlab.com/exadra37-docker/elixir/elixir%20by%20%40Exadra37.%20%23docker%20%23dockercontainers%20%23myelixirstatus) or in any other channel of your preference. +* Consider to [offer me](https://www.paypal.me/exadra37) a coffee, a beer, a dinner or any other treat 😎. + +[Menu](#menu) + + +# EXPLICIT VERSIONING + +This repository uses [Explicit Versioning](https://gitlab.com/exadra37-versioning/explicit-versioning) schema. + +[Menu](#menu) + + +# DISCLAIMER I code for passion and when coding I like to do as it pleases me... You know I do this in my free time, thus I want to have fun and enjoy it ;). Professionally I will do it as per company guidelines and standards. + +[Menu](#menu) diff --git a/bin/elixir b/bin/elixir new file mode 100755 index 0000000..cffde09 --- /dev/null +++ b/bin/elixir @@ -0,0 +1,1687 @@ +#!/bin/bash + +# @link https://elixir-lang.org/getting-started/debugging.html +# @link https://s3.us-east-2.amazonaws.com/ferd.erlang-in-anger/text.v1.1.0.pdf +# @link https://mfeckie.github.io/Remote-Profiling-Elixir-Over-SSH/ +# @link https://github.com/ferd/recon + +set -eu + +Show_Help() +{ + cat << HEREDOC + +ELIXIR DOCKER STACK + +A docker developemnt stack that includes Elixir, Phoenix, Erlang, Oberver and Postgres. + + +ELIXIR CLI USAGE: + + elixir [options] [.exs file] [data] + + +ELIXIR DOCKER STACK USAGE: + + elixir [options] [command] [args] + + +ELIXIR DOCKER STACK OPTIONS: + + -d, --detached Run the docker container detached from the terminal. + + --db, --database Starts the container with the Postgres database up. + + --df, --dockerfile The dockerfile to run a container. + Defaults to: debian + $ elixir --dockerfile alpine up + $ elixir --dockerfile debian.slim up + + --ev, --elixir-version The Elixir version to be used for the docker tag, + Defaults to the latest Elixir version: 1.8 + $ elixir --elixir-version 1.3.4 up + + -h, --help Shows the help for the Elixir CLI and Stack. + $ elixir -h + $ elixir --help + $ elixir --help stack + + -it, --interactive-tty Run the docker container attached to the terminal. + $ elixir -it up + + --mix-env Sets the MIX_ENV var in the container. + Defaults to dev. + $ mix --mix-env test ecto.create + + -p, --publish Map the host ports to the docker container ports. + Defaults to: 4000:4000 . + $ elixir --publish 8000:4000 up + + --pv, --phoenix-version The Phoenix version to be installed. + Defaults to the last release, eg: 1.4.3 . + $ elixir --phoenix-version 1.3.4 up + + -u, --user The user we want to run inside the container, + Defaults to user, eg: elixir . + $ elixir --user root shell + + --verbose Enables verbose output for the docker stack. + Defaults to level 0, and can go until level 4. + $ elixir --verbose 1 up + $ elixir --verbose 2 shell + $ elixir --verbose 3 observer + $ elixir --verbose 4 build + + --wa, --wait-dummy-app Seconds to wait for the app dummy container to be ready. + Defaults to 1 second. + $ elixir --wait-dummy-app 3 up + + --wd, --wait-database Seconds to wait for the database is up and running. + Defaults to 5 seconds. + $ elixir --wait-database 10 new-database myapp_test + + +ELIXIR DOCKER STACK COMMANDS: + + Runs Elixir inside the container as it would in the host. + $ elixir --help + + build Builds the docker image for the given dodkerfile. + Defaults to build from: debian . + $ elixir build + $ elixir build alpine + + container-logs Shows a tail -f of the container logs. + $ elixir container-logs + + down Stops and removes the running container. + $ elixir down + + iex The Elixir IEx shell. + $ iex [options] + + mix The Elixir mix tool. + $ mix [options] + $ mix help + $ mix new elixir-project + $ mix phx.new phoenix-app + + new-database Creates a new database. + Defaults to the current folder name with suffix "_dev". + $ elixir new-database + $ elixir new-database acme + + pgcli A better shell for Postgres, includes auto-completion. + $ elixir pgcli [options] + + observer Starts the Observer GUI from an IEx shell. + $ elixir observer + + observer-cli Allows to start from IEx the Observer CLI(like Linux HTOP). + $ elixir observer-cli + + up Starts the Elixir docker stack. + $ elixir up + $ elixir --db up + $ elixir --dockerfile alpine up + $ elixir -it --publish 8000:4000 up + $ elixir --elixir-version 1.3 --phoenix-version 1.3.4 --db up + + shell A shell inside the container for the Elixir docker stack. + $ elixir shell + $ elixir -u root shell + +HEREDOC + +} + +################################################################################ +# FUNCTIONS +################################################################################ + + Print_Text_With_Label() + { + ############################################################################ + # INPUT + ############################################################################ + + local label_text="${1? Missing label to print!!!}" + + local text="${2? Missing text to print!!!}" + + local verbosity_print_level="${3? Missing verbosity print level!!!}" + + local label_background_color="${4:-42}" + + local text_background_color="${5:-229}" + + + ############################################################################ + # EXECUTION + ############################################################################ + + case "${verbosity_print_level}" in + "1" ) + local label_background_color="40" + ;; + "2" ) + local label_background_color="44" + ;; + "3" ) + local label_background_color="45" + ;; + "4" ) + local label_background_color="46" + ;; + * ) + local label_background_color="42" + esac + + if [ "${verbosity_print_level}" -le "${VERBOSE_LEVEL}" ]; then + printf "\n\e[1;${label_background_color}m ${label_text}:\e[30;48;5;${text_background_color}m ${text} \e[0m \n" + fi + } + + Print_Text() + { + ############################################################################ + # INPUT + ############################################################################ + + local text="${1? Missing text to print!!!}" + + local verbosity_print_level="${2? Missing verbosity print level!!!}" + + local text_color="${3:-44}" + + + ############################################################################ + # EXECUTION + ############################################################################ + + if [ "${verbosity_print_level}" -le "${VERBOSE_LEVEL}" ]; then + printf "\n\e[1;${text_color}m ${text} \e[0m \n" + fi + } + + Print_Fatal_Error() + { + ############################################################################ + # INPUT + ############################################################################ + + local text="${1? Missing text to print for the Fatal Error!!!}" + + + ############################################################################ + # EXECUTION + ############################################################################ + + printf "\n\e[1;41m FATAL ERROR:\e[30;48;5;229m ${text} \e[0m \n\n" + } + + Create_Env_File_If_Not_Exists() + { + ############################################################################ + # INPUT + ############################################################################ + + local suffix="${1:-.docker-container}" + + local example_suffix="${2:--example}" + + + ############################################################################ + # EXECUTION + ############################################################################ + + # Useful to pass environment variables into the container. + if [ ! -f .env"${suffix}" ]; then + if [ -f .env"${suffix}${example_suffix}" ]; then + cp .env"${suffix}${example_suffix}" .env"${suffix}" + else + touch .env"${suffix}" + fi + fi + } + + # One Liner for testing in shell: + # → if sudo -h > /dev/null 2>&1 ; then echo 'Sudo is enabled.' ; else echo 'Sudo is not enabled' ; fi + Sudo_Exists() + { + ############################################################################ + # EXECUTION + ############################################################################ + + if sudo -h > /dev/null 2>&1; then + # sudo exists + return 0 + fi + + # sudo doesn't exist + return 1 + } + + Sudo_Prefix() + { + ############################################################################ + # EXECUTION + ############################################################################ + + if Sudo_Exists; then + echo 'sudo' + return + fi + + echo "" + } + + Setup_X11_Server_Display() + { + ############################################################################ + # INPUT + ############################################################################ + + local host_setup_dir="${1? Missing host setup dir!!!}" + + local xauth_display="${2:-:0}" + + + ############################################################################ + # VARS + ############################################################################ + + local xauth="${host_setup_dir}"/.docker.xauth + + + ############################################################################ + # EXECUTION + ############################################################################ + + # @link http://wiki.ros.org/docker/Tutorials/GUI#The_isolated_way + touch "${xauth}" + xauth nlist "${xauth_display}" | sed -e 's/^..../ffff/' | xauth -f "${xauth}" nmerge - + + echo "${xauth}" + } + + Is_Umbrella_App() + { + ############################################################################ + # INPUT + ############################################################################ + + local path="${1? Missing path to check if is an umbrella app.!!!}" + + + ############################################################################ + # EXECUTION + ############################################################################ + + if [ -f "${path}"/mix.exs ]; then + grep -qw "apps_path:" "${path}"/mix.exs 2&> /dev/null + return $? + fi + + # Not an Umbrella App. + return 1 + } + + Set_Global_Paths_For_Umbrella_App() + { + + ############################################################################ + # EXECUTION + ############################################################################ + + if Is_Umbrella_App "${PWD}/.."; then + APP_HOST_DIR="${PWD}/.." + APP_CONTAINER_RELATIVE_PATH=workspace/apps + fi + + if Is_Umbrella_App "${PWD}/../.."; then + APP_HOST_DIR="${PWD}/../.." + APP_CONTAINER_RELATIVE_PATH=workspace/apps/"${APP_NAME}" + fi + } + +################################################################################ +# DOCKER FUNCTIONS +################################################################################ + + Is_App_With_Database() + { + ############################################################################ + # INPUT + ############################################################################ + + local app_name="${1? Missing app name!!!}" + + local config_file=config/dev.exs + + if [ ! -f "${config_file}" ]; then + local config_file="${app_name}/${config_file}" + fi + + + ############################################################################ + # EXECUTION + ############################################################################ + + Print_Text_With_Label "Config file Path" "${config_file}" "3" + + # Converts `my_app_name` to `myappname` do that we can use a grep case + # insensitive search on the string `MyAppName.Repo`. + local repo_name="${app_name/_/}.Repo" + Print_Text_With_Label "Repository Name" "${repo_name}" "3" + + grep -iq "${repo_name}," "${config_file}" 2&> /dev/null + + return $? + } + + Is_Not_Present_Docker_Image() + { + ############################################################################ + # INPUT + ############################################################################ + + local _image_name="${1}" + + ############################################################################ + # EXECUTION + ############################################################################ + + [ -z $( ${SUDO_PREFIX} docker images -q "${_image_name}" ) ] && return 0 || return 1 + } + + Get_Container_Ip_Address() + { + ############################################################################ + # INPUT + ############################################################################ + + local container_name="${1? Missing container name!!!}" + + + ############################################################################ + # EXECUTION + ############################################################################ + + echo -n $( ${SUDO_PREFIX} docker exec -it ${container_name} sh -c 'echo -n $(hostname -i)' ) + } + + Get_Container_Username_UID() + { + ############################################################################ + # INPUT + ############################################################################ + + local docker_image="${1? Missing docker image!!!}" + local user_name="${2? Missing user name to get the UID!!!}" + + + ############################################################################ + # EXECUTION + ############################################################################ + + echo -n $( ${SUDO_PREFIX} docker run --rm -it --user ${user_name} ${docker_image} sh -c 'echo -n $(id -u)' ) + } + + Get_Docker_Image_Tag() + { + ############################################################################ + # INPUT + ############################################################################ + + local elixir_version="${1? Missing Elixir Version!!!}" + + local phoenix_version="${2? Missing Phoenix version!!!}" + + local dockerfile="${3? Missing variant for docker image!!!}" + + + ############################################################################ + # EXECUTION + ############################################################################ + + if [ "${dockerfile}" = "observer-debian" ]; then + echo "${elixir_version}" + else + echo "${elixir_version}_${phoenix_version}_${dockerfile}" + fi + } + + Create_Docker_Network_If_Not_Exists() + { + ############################################################################ + # INPUT + ############################################################################ + + local network_name="${1? Missing network name!!!}" + + ############################################################################ + # EXECUTION + ############################################################################ + + ${SUDO_PREFIX} docker network create "${network_name}" &> /dev/null || true + } + + Create_Docker_Volume() + { + ############################################################################ + # INPUT + ############################################################################ + + local container_name="${1? Missing container name!!!}" + + + ############################################################################ + # EXECUTION + ############################################################################ + + Print_Text_With_Label "CREATING DOCKER VOLUME:" "${container_name}" "2" + + ${SUDO_PREFIX} docker volume create "${container_name}" + } + + Build_Docker_Image() + { + ############################################################################ + # INPUT + ############################################################################ + + local image_name="${1? Missing docker image name!!!}" + + local dockerfile="${2? Missing variant for docker image!!!}" + + local erlang_version="${3? Missing Erlang version!!!}" + + local elixir_version="${4? Missing Elixir version!!!}" + + local phoenix_version="${5? Missing Phoenix version!!!}" + + local mix_env="${6? Missing mix env value!!!}" + + local build_path="${7? Missing build path for docker image!!!}" + + shift 7 + + + ############################################################################ + # VARS + ############################################################################ + + if [ "${dockerfile}" = "observer-debian" ]; then + + local image_name=exadra37/observer + + local elixir_version=latest + + fi + + local tag="$( Get_Docker_Image_Tag "${elixir_version}" "${phoenix_version}" "${dockerfile}" )" + + local docker_image="${image_name}:${tag}" + + local dockerfile_path="${build_path}"/${dockerfile}".Dockerfile" + + + ############################################################################ + # EXECUTION + ############################################################################ + + Print_Text_With_Label "DOCKER IMAGE" "${docker_image}" "1" + + Print_Text_With_Label "BUILDING FROM DOCKERFILE" "${dockerfile_path}" "2" + + # --no-cache \ + # --force-rm \ + # --pull \ + ${SUDO_PREFIX} docker build \ + --file "${dockerfile_path}" \ + --build-arg "DOCKER_ERLANG_VERSION=${erlang_version}" \ + --build-arg "DOCKER_ELIXIR_VERSION=${elixir_version}" \ + --build-arg "PHOENIX_VERSION=${phoenix_version}" \ + --build-arg "MIX_ENV=${mix_env}" \ + --tag ${docker_image} \ + "${build_path}" + } + + Docker_Container_Is_Running() + { + ############################################################################ + # INPUT + ############################################################################ + + local container_name="${1? Missing container name!!!}" + + + ############################################################################ + # EXECUTION + ############################################################################ + + ${SUDO_PREFIX} docker container ls -a | grep -qw "${container_name}" - + + return $? + } + + Attach_To_App_Container() + { + Print_Text_With_Label "FUNCTION" "Attach_To_App_Container" "4" + + ############################################################################ + # INPUT + ############################################################################ + + local app_container_name="${1? Missing app container name!!!}" + + local container_username="${2? Missing container userNAME!!!}" + + local background_mode="${3? Missing backround mode to run the container!!!}" + + local run_command="${4? Missing command to run in the container!!!}" + + shift 4 + + local args="${@}" + + + ############################################################################ + # EXECUTION + ############################################################################ + + Print_Text_With_Label "ATTACHING TO CONTAINER" "${app_container_name}" "1" + + Print_Text_With_Label "INVOKED COMMAND" "${run_command} ${args}" "2" + + Print_Text_With_Label "BACKGROUND MODE" "${background_mode}" "3" + + APP_NODE_NAME="${APP_NAME}@$( Get_Container_Ip_Address ${app_container_name} )" + + ${SUDO_PREFIX} docker exec \ + --user ${container_username} \ + --env "APP_NODE_NAME=${APP_NODE_NAME}" \ + --env "APP_NODE_COOKIE=${ERLANG_COOKIE}" \ + ${background_mode} \ + ${app_container_name} \ + ${run_command} ${args} + } + + Start_Or_Attach_To_App_Container() + { + Print_Text_With_Label "FUNCTION" "Start_Or_Attach_To_App_Container" "4" + + ############################################################################ + # INPUT + ############################################################################ + + local image_name="${1? Missing docker image name!!!}" + + local erlang_version="${2? Missing Erlang version!!!}" + + local elixir_version="${3? Missing Elixir version!!!}" + + local phoenix_version="${4? Missing Phoenix version!!!}" + + local dockerfile="${5? Missing docker image variant!!!}" + + local app_name="${6? Missing the APP name!!!}" + + local app_network="${7? Missing app network}" + + local app_container_name="${8? Missing app container name!!!}" + + local container_username="${9? Missing container userNAME!!!}" + + local port_map="${10? Missing port map!!!}" + + local mix_env="${11? Missing mix env value!!!}" + + local env_file="${12? Missing the env file!!!}" + + local background_mode="${13? Missing backround mode to run the container!!!}" + + local host_setup_dir="${14? Missing host dir for Elixir stack setup!!!}" + + local build_path="${15? Missing build path for docker image!!!}" + + local run_command="${16? Missing command to run in the container!!!}" + + shift 16 + + local args="${@}" + + + ############################################################################ + # VARS + ############################################################################ + + local tag="$( Get_Docker_Image_Tag "${elixir_version}" "${phoenix_version}" "${dockerfile}" )" + + local docker_image="${image_name}:${tag}" + + local xauth_sock="/tmp/.X11-unix" + + local xauth=$( Setup_X11_Server_Display "${host_setup_dir}" ) + + local publish_ports="" + + if [ "${port_map}" != ":" ]; then + local publish_ports="--publish 127.0.0.1:${port_map}" + fi + + Set_Global_Paths_For_Umbrella_App + + Print_Text_With_Label "APP_HOST_DIR" "${APP_HOST_DIR}" "2" + + Print_Text_With_Label "APP_CONTAINER_RELATIVE_PATH" "${APP_CONTAINER_RELATIVE_PATH}" "2" + + + ############################################################################ + # EXECUTION + ############################################################################ + + if Is_Not_Present_Docker_Image "${docker_image}"; then + + Print_Text_With_Label "DOCKER IMAGE" "${docker_image}" "0" + + Print_Text_With_Label "TAG" "${tag}" "0" + + Print_Text_With_Label "DOCKERFILE" "${dockerfile}" "0" + + Print_Text_With_Label "WARNING" "Missing docker image for >>> ${app_name} <<< APP. Please wait until we build the image." "1" + + Build_Docker_Image \ + "${image_name}" \ + "${dockerfile}" \ + "${erlang_version}" \ + "${elixir_version}" \ + "${phoenix_version}" \ + "${mix_env}" \ + "${build_path}" + fi + + if Docker_Container_Is_Running "${app_container_name}"; then + + Attach_To_App_Container \ + "${app_container_name}" \ + "${container_username}" \ + "${background_mode}" \ + "${run_command}" \ + ${@} + + exit 0 + fi + + Print_Text_With_Label "STARTING DOCKER IMAGE" "${docker_image}" "1" + + Print_Text_With_Label "INVOKED COMMAND" "${run_command} ${args}" "2" + + Print_Text_With_Label "DOCKERFILE" "${dockerfile}" "3" + + Print_Text_With_Label "TAG" "${tag}" "3" + + Print_Text_With_Label "CONTAINER USERNAME" "${container_username}" "3" + + Print_Text_With_Label "APP NETWORK" "${app_network}" "3" + + local env_file_option="" + + if [ -f "${env_file}" ]; then + local env_file_option="--env-file ${env_file}" + fi + + ${SUDO_PREFIX} docker run \ + --rm \ + ${background_mode} \ + ${env_file_option} \ + ${publish_ports} \ + ${CONTAINER_ENV} \ + --env "APP_NODE_NAME=${APP_NODE_NAME}" \ + --env "APP_NODE_COOKIE=${ERLANG_COOKIE}" \ + --env "MIX_ENV=${mix_env}" \ + --env "XAUTHORITY=${xauth}" \ + --name "${app_container_name}" \ + --hostname "${app_name}" \ + --user "${container_username}" \ + --network "${app_network}" \ + --workdir /home/"${container_username}/${APP_CONTAINER_RELATIVE_PATH}" \ + --volume "${APP_HOST_DIR}":/home/"${container_username}"/workspace \ + --volume "${app_container_name}_${tag}_var_lib_postgresql":/var/lib/postgresql \ + --volume "${app_container_name}_${tag}_var_log_postgresql":/var/log/postgresql \ + --volume "${app_container_name}_${tag}_config_sublimetext_3":/home/"${container_username}"/.config/sublime-text-3 \ + --volume "/tmp/.X11-unix":"/tmp/.X11-unix":ro \ + --volume "${xauth}":"${xauth}":ro \ + "${docker_image}" \ + ${run_command} ${args} + } + + Start_Dummy_App_Container() + { + ############################################################################ + # INPUT + ############################################################################ + + local image_name="${1? Missing docker image name!!!}" + + local erlang_version="${2? Missing Erlang version!!!}" + + local elixir_version="${3? Missing Elixir version!!!}" + + local phoenix_version="${4? Missing Phoenix version!!!}" + + local dockerfile="${5? Missing docker image variant!!!}" + + local app_name="${6? Missing the APP name!!!}" + + local app_network="${7? Missing app network}" + + local app_container_name="${8? Missing app container name!!!}" + + local container_username="${9? Missing container userNAME!!!}" + + local port_map="${10? Missing port map!!!}" + + local mix_env="${11? Missing mix env value!!!}" + + local env_file="${12? Missing the env file!!!}" + + local host_setup_dir="${13? Missing host dir for Elixir stack setup!!!}" + + local build_path="${14? Missing build path for docker image!!!}" + + local seconds_to_wait_dummy_app_is_ready="${15? Missing seconds to wait until dummy app container is ready!!!}" + + shift 15 + + + ############################################################################ + # EXECUTION + ############################################################################ + + # We need a dummy Docker container running before we start any real + # process on it, so that we can run Elixir or Phoenix apps with a full + # qualified node name, byt getting the IP address of the dummy container. + if ! Docker_Container_Is_Running "${app_container_name}"; then + + Print_Text "STARTING A DUMMY CONTAINER" "4" + + Start_Or_Attach_To_App_Container \ + "${image_name}" \ + "${erlang_version}" \ + "${elixir_version}" \ + "${phoenix_version}" \ + "${dockerfile}" \ + "${app_name}" \ + "${app_network}" \ + "${app_container_name}" \ + "${container_username}" \ + "${port_map}" \ + "${mix_env}" \ + "${env_file}" \ + "-td" \ + "${host_setup_dir}" \ + "${build_path}" \ + "" + + # need to give time for the container be available, before we try to + # attach to it in the next command. + sleep ${seconds_to_wait_dummy_app_is_ready} + fi + } + + Attach_To_Database_Container() + { + Print_Text_With_Label "FUNCTION" "Attach_To_Database_Container" "4" + + ############################################################################ + # INPUT + ############################################################################ + + local database_container_name="${1? Missing database container name!!!}" + local database_user="${2? Missing database user!!!}" + local run_command="${3? Missing command to run in the container!!!}" + + shift 3 + + local args="${@}" + + + ############################################################################ + # EXECUTION + ############################################################################ + + Print_Text_With_Label "INVOKED COMMAND" "${run_command} ${args}" "2" + + if [ "${run_command}" = "postgres" ]; then + Print_Text_With_Label "WARNING" "Postgres database is already running. You can only attach to run commands, eg: createdb ..." "1" + return + fi + + ${SUDO_PREFIX} docker exec \ + -it \ + --user "${database_user}" \ + "${database_container_name}" \ + ${run_command} ${args} + } + + Start_Or_Attach_To_Database_Container() + { + Print_Text_With_Label "FUNCTION" "Start_Or_Attach_To_Database_Container" "4" + + ############################################################################ + # INPUT + ############################################################################ + + local app_name="${1? Missing app name!!!}" + + local app_network="${2? Missing app network!!!}" + + local database_image="${3? Missing database image name!!!}" + + local database_data_dir="${4? Missing database data dir!!!}" + + local database_user="${5? Missing database user!!!}" + + local database_container_name="${6? Missing database container name!!!}" + + local background_mode="${7? Missing background mode to run the container!!!}" + + local run_command="${8? Missing command to run in the container!!!}" + + shift 8 + + local args="${@}" + + + ############################################################################ + # EXECUTION + ############################################################################ + + Print_Text_With_Label "DATABASE CONTAINER" "${database_container_name}" "2" + + if [ ! -d "${database_data_dir}" ]; then + + Print_Text_With_Label "CHECK POINT" "Fixing database data dir permissions!!!" "4" + + local user_uid=$( Get_Container_Username_UID "${database_image}" "${database_user}" ) + + Print_Text_With_Label "USER UID (${database_user})" "${user_uid}" "3" + + mkdir -p "${database_data_dir}" + + ${SUDO_PREFIX} chown -R ${user_uid}:${user_uid} "${database_data_dir}/.." + fi + + if Docker_Container_Is_Running "${database_container_name}"; then + + Attach_To_Database_Container \ + "${database_container_name}" \ + "${database_user}" \ + ${run_command} + + return 0 + fi + + Print_Text_With_Label "INVOKED COMMAND" "${run_command} ${args}" "2" + + ${SUDO_PREFIX} docker run \ + --rm \ + "${background_mode}" \ + --hostname "${app_name}_database" \ + --user "${database_user}" \ + --name "${database_container_name}" \ + --network "${app_network}" \ + --volume "${database_data_dir}":/var/lib/postgresql/data \ + "${database_image}" ${run_command} ${args} + } + + Run_Database_Command() + { + Print_Text_With_Label "FUNCTION" "Run_Database_Command" "4" + + ############################################################################ + # INPUT + ############################################################################ + + local app_name="${1? Missing app name!!!}" + + local app_network="${2? Missing app network!!!}" + + local database_image="${3? Missing database image name!!!}" + + local database_data_dir="${4? Missing database data dir!!!}" + + local database_user="${5? Missing database container userNAME!!!}" + + local database_container_name="${6? Missing database container name!!!}" + + local start_database_command="${7? Missing command to start database!!!}" + + local seconds_to_wait_database_is_running="${8? Missing seconds to wait database to be running!!!}" + + local run_command="${9? Missing command to run in the container!!!}" + + shift 9 + + + ############################################################################ + # EXECUTION + ############################################################################ + + Print_Text_With_Label "INVOKED COMMAND" "${run_command}" "4" + + if ! Docker_Container_Is_Running "${database_container_name}"; then + + Start_Or_Attach_To_Database_Container \ + "${app_name}" \ + "${app_network}" \ + "${database_image}" \ + "${database_data_dir}" \ + "${database_user}" \ + "${database_container_name}" \ + "--detach" \ + "${start_database_command}" + + Print_Text "Waiting for database engine to start..." "0" + + sleep ${seconds_to_wait_database_is_running} + fi + + Start_Or_Attach_To_Database_Container \ + "${app_name}" \ + "${app_network}" \ + "${database_image}" \ + "${database_data_dir}" \ + "${database_user}" \ + "${database_container_name}" \ + "-it" \ + "${run_command}" + } + + Start_Observer_Container() + { + # to implement over ssh tunnel: + # * https://sgeos.github.io/elixir/erlang/observer/2016/09/16/elixir_erlang_running_otp_observer_remotely.html + # * https://github.com/Stratus3D/dotfiles/blob/master/scripts/tools/epmd_port_forwarder + # * https://github.com/Nebo15/k8s-utils + # * https://chazsconi.github.io/2017/04/22/observing-remote-elixir-docker-nodes.html + # + # http://jbavari.github.io/blog/2016/03/11/using-erlang-observer-on-a-remote-elixir-server/ + + ############################################################################ + # INPUT + ############################################################################ + + local host_setup_dir="${1? Missing host setup dir!!!}" + + local app_name="${2? Missing app name!!!}" + + local app_network="${3? Missing app network!!!}" + + local app_container_name="${4? Missing app container_name!!!}" + + local erlang_cookie="${5? Missing the Erlang cookie!!!}" + + local observer_container_username="${6? Missing Observer container userNAME!!!}" + + shift 6 + + Print_Text_With_Label "HOST SETUP DIR" "${host_setup_dir}" "3" + + Print_Text_With_Label "APP NAME" "${app_name}" "3" + + Print_Text_With_Label "APP NETWORK" "${app_network}" "3" + + Print_Text_With_Label "APP CONTAINER NAME" "${app_container_name}" "3" + + Print_Text_With_Label "ERLANG COOKIE" "${erlang_cookie}" "3" + + if ! Docker_Container_Is_Running "${app_container_name}"; then + Print_Fatal_Error "The App container >>> ${app_container_name} <<< is not running. Are you in the APP root folder?" + return + fi + + local app_ip_address=$( Get_Container_Ip_Address "${app_container_name}" ) + + Print_Text_With_Label "APP IP ADDRESS" "${app_ip_address}" "3" + + case "${1:-}" in + "htop" ) + local observer_command="observer-cli ${app_name} ${app_ip_address} ${erlang_cookie}" + local observer_container_name="${app_name}_observer-htop" + shift 1 + ;; + + "shell" ) + local observer_command="zsh" + local observer_container_name="${app_name}_observer-shell" + shift 1 + ;; + + "" ) + local observer_command="observer ${app_name} ${app_ip_address} ${erlang_cookie}" + local observer_container_name="${app_name}_observer" + ;; + + * ) + Print_Fatal_Error "Unsupported: ${input}" + + esac + + ############################################################################ + # CONSTANTS + ############################################################################ + + local OBSERVER_DOCKER_IMAGE="exadra37/observer" + + + ############################################################################ + # EXECUTION + ############################################################################ + + if Is_Not_Present_Docker_Image "${OBSERVER_DOCKER_IMAGE}"; then + + Print_Text_With_Label "DOCKER IMAGE" "${OBSERVER_DOCKER_IMAGE}" "0" + + Print_Fatal_Error "Build first the docker image with: elixir build observer-debian" + + exit 1 + fi + + local xauth=$( Setup_X11_Server_Display "${host_setup_dir}" ) + + Print_Text_With_Label "OBSERVER COMMAND" "${observer_command}" "2" + + ${SUDO_PREFIX} docker run \ + --rm \ + -it \ + --user "${observer_container_username}" \ + --hostname "${observer_container_name}" \ + --name "${observer_container_name}" \ + --network "${app_network}" \ + --volume="/tmp/.X11-unix":"/tmp/.X11-unix":ro \ + --volume="${xauth}":"${xauth}":ro \ + --env="XAUTHORITY=${xauth}" \ + "${OBSERVER_DOCKER_IMAGE}" ${observer_command} ${@} + } + + Stop_And_Remove_Docker_Containers() + { + ############################################################################ + # EXECUTION + ############################################################################ + + for container_name in "${@}"; do + + if Docker_Container_Is_Running "${container_name}" ; then + + # no need to remove the containers explicitly, once they where started + # with the `--rm` flag + ${SUDO_PREFIX} docker stop "${container_name}" + fi + + done + } + +################################################################################ +# MAIN +################################################################################ + + Main() + { + ############################################################################ + # CONSTANTS + ############################################################################ + + # from `/home/username/developer/acme` we will get `developer/acme` + CURRENT_PATH="${PWD#*${USER}/}" + # from `developer/acme` we get `developer_acme` + #APP_NAME="${CURRENT_PATH//\//_}" + + APP_NAME="${PWD##*/}" + + APP_NODE_NAME="" + + ERLANG_COOKIE="super-long-secret-cookie" + + ELIXIR_DOCKER_STACK_INSTALL_DIR=${ELIXIR_DOCKER_STACK_INSTALL_DIR:-~/elixir-docker-stack} + + ELIXIR_DOCKER_STACK_DATA_DIR=${ELIXIR_DOCKER_STACK_DATA_DIR:-~/.elixir-docker-stack-data} + + SUDO_PREFIX=$(Sudo_Prefix) + + + ############################################################################ + # ENV + ############################################################################ + + local image_name=exadra37/elixir-phoenix + + local dockerfile=debian + + local erlang_version=21.3.3 + + local elixir_version=1.8 + + local phoenix_version=1.4.3 + + local phoenix_command=phx.server + + local build_path="${ELIXIR_DOCKER_STACK_INSTALL_DIR}"/docker/build + + local background_mode="-it" + + local app_port_map="4000:4000" + + local env_file=".env.app-docker-container" + + local database_image=postgres:11-alpine + + local database_user=postgres + + local database_command=postgres + + local seconds_to_wait_dummy_app_is_ready=1 + + local seconds_to_wait_database_is_running=5 + + local mix_env=dev + + local stack_defaults_file=.elixir-docker-stack-defaults + + # We can override any of the above variables in the .elixir-docker-stack-defaults + # file in the home directory or from the root for the project we are + # working on. + # + # Bear in mind that some can be override if provided as an argument or option + # to this bash script. + if [ -f ~/"${stack_defaults_file}" ]; then + source ~/"${stack_defaults_file}" + fi + + # It will override any variable already declared the ~/.env.elixir-docker-stack-defaults. + # + # Bear in mind that some can be override if provided as an argument or option + # to this bash script. + if [ -f "${stack_defaults_file}" ]; then + source "${stack_defaults_file}" + fi + + # from 1.4.0 assigns 1.4 + local phoenix_major_version="${phoenix_version%.*}" + + # Phoenix framework installation procedure changed from 1.4 onwards. + if [ "${phoenix_major_version}" \< "1.4" ]; then + phoenix_command=phoenix.server + fi + + # from `developer/acme/my-app` we get `~/.elixir-docker-stack-data/developer_acme_my-app` + local host_setup_dir="${ELIXIR_DOCKER_STACK_DATA_DIR}/${CURRENT_PATH//\//_}" + + local container_username="" + + local app_username=elixir + + local app_container_name="${APP_NAME}_app" + + local VERBOSE_LEVEL=0 + + local app_network="${APP_NAME}_network" + + # by default it will be assigned $app_port_map when running commands: + # * up + # * phx.server, phoenix.server + # * phx.new, phoenix.new + # we can override with -p or --publish + # + # ":" means no port map + local port_map=":" + + local database_engine=postgres + + local database_data_dir="${host_setup_dir}"/${database_engine}/data + + local database_container_name="${APP_NAME}_${database_engine}" + + local observer_username=observer + + local APP_HOST_DIR="${PWD}" + + local APP_CONTAINER_RELATIVE_PATH=workspace + + local CONTAINER_ENV="" + + + ############################################################################ + # PARSE INPUT / EXECUTION + ############################################################################ + + mkdir -p "${host_setup_dir}" + + Create_Docker_Network_If_Not_Exists "${app_network}" + + local run_command=${0##*/} + + for input in "${@}"; do + case "${input}" in + + -d | --detach ) + Print_Text_With_Label "OPTION" "-d, --detach" "4" + + background_mode="--detach" + shift 1 + ;; + + --db | --database ) + Print_Text_With_Label "OPTION" "--db, --database" "4" + + shift 1 + + Start_Or_Attach_To_Database_Container \ + "${APP_NAME}" \ + "${app_network}" \ + "${database_image}" \ + "${database_data_dir}" \ + "${database_user}" \ + "${database_container_name}" \ + "--detach" \ + "${database_command}" + ;; + + --db-image | --database-image ) + Print_Text_With_Label "OPTION" "--df, --dockerfile" "4" + + local database_image="${2? Missing database image to use!!!}" + shift 2 + ;; + + --df | --dockerfile ) + Print_Text_With_Label "OPTION" "--df, --dockerfile" "4" + + local dockerfile="${2? Missing variant for docker image... eg: alpine}" + + shift 2 + ;; + + -e | --env ) + + local CONTAINER_ENV="${CONTAINER_ENV} --env ${2? Missing env variable !!!}" + shift 2 + ;; + + --ev | --elixir-version ) + Print_Text_With_Label "OPTION" "--ev, --elixir-version" "4" + + local elixir_version="${2? Missing Elixir version!!!}" + shift 2 + ;; + + -h | --help ) + Print_Text_With_Label "OPTION" "-h, --help" "4" + + shift 1 + + if [ "${1:-}" = "stack" ]; then + Show_Help + exit 0 + fi + + local run_command="elixir --help" + ;; + + -it ) + Print_Text_With_Label "OPTION" "-it" "4" + + local background_mode="-it" + shift 1 + ;; + + --mix-env ) + Print_Text_With_Label "OPTION" "--mix-env" "4" + + local mix_env="${2? Missing mix env value. One of dev,prod or test!!!}" + ;; + + --no-cache ) + # not implemented yet + ;; + + -p | --publish ) + Print_Text_With_Label "OPTION" "-p, --publish" "4" + + local port_map=${2? Missing host port map for the container, eg: 3000:3000 !!!} + shift 2 + ;; + + --pv | --phoenix-version ) + Print_Text_With_Label "OPTION" "--pv, --phoenix-version" "4" + + local phoenix_version="${2? Missing Phoenix version!!!}" + shift 2 + ;; + + -u | --user ) + Print_Text_With_Label "OPTION" "-u, --user" "4" + + local container_username=${2? Missing user for container!!!} + shift 2 + ;; + + --verbose ) + Print_Text_With_Label "OPTION" "--verbose" "4" + + shift 1 + + local VERBOSE_LEVEL=${1:-${VERBOSE_LEVEL}} + + if [ "$#" -ge 1 ]; then + shift 1 + fi + ;; + + --wa | --wait-dummy-app ) + Print_Text_With_Label "OPTION" "--wa, --wait-dummy-app" "4" + + local seconds_to_wait_dummy_app_is_ready="${2? Missing seconds to wait for dummy app container to be ready!!!}" + shift 2 + ;; + + --wd | --wait-database ) + Print_Text_With_Label "OPTION" "--wd, --wait-database" "4" + + local seconds_to_wait_database_is_running="${2? Missing seconds to wait for the database to be running!!!}" + shift 2 + ;; + + build ) + Print_Text_With_Label "COMMAND" "build" "4" + + Build_Docker_Image \ + "${image_name}" \ + "${2:-${dockerfile}}" \ + "${erlang_version}" \ + "${elixir_version}" \ + "${phoenix_version}" \ + "${mix_env}" \ + "${build_path}" + + exit 0 + ;; + + container-logs ) + Print_Text_With_Label "COMMAND" "container-logs" "4" + + ${SUDO_PREFIX} docker logs -f "${app_container_name}" + exit 0 + ;; + + down ) + Print_Text_With_Label "COMMAND" "down" "4" + + Stop_And_Remove_Docker_Containers \ + "${app_container_name}" \ + "${database_container_name}" + + exit 0 + ;; + + new-database ) + Print_Text_With_Label "COMMAND" "new-database" "4" + + shift 1 + local database_name="${1:-${APP_NAME}_dev}" + + if [ "$#" -ge 1 ]; then + shift 1 + fi + + Run_Database_Command \ + "${APP_NAME}" \ + "${app_network}" \ + "${database_image}" \ + "${database_data_dir}" \ + "${database_user}" \ + "${database_container_name}" \ + "${database_command}" \ + "${seconds_to_wait_database_is_running}" \ + "createdb -O postgres -U postgres ${database_name}" + + exit 0 + ;; + + observer ) + Print_Text_With_Label "COMMAND" "observer" "4" + + shift 1 + + if [ -z "${container_username}" ]; then + local container_username="${observer_username}" + fi + + # TODO: + # * observer_cli binary seems not be able to connect to the remote node + # frStart_Or_Attach_To_App_Container + # * https://chazsconi.github.io/2017/04/22/observing-remote-elixir-docker-nodes.html + #run_command="observer_cli elixir@b09b4f769088 ${ERLANG_COOKIE}" + + Start_Observer_Container \ + "${host_setup_dir}" \ + "${APP_NAME}" \ + "${app_network}" \ + "${app_container_name}" \ + "${ERLANG_COOKIE}" \ + "${container_username}" \ + ${@} + + exit 0 + ;; + + pgcli ) + Print_Text_With_Label "COMMAND" "pgcli" "4" + + run_command=${1} + shift 1 + + break + ;; + + new | phoenix.new | phx.new ) + Print_Text_With_Label "COMMAND" "${1}" "4" + + # break parsing the input if --version option is given. + case "${2:-}" in + --version ) + break + ;; + esac + + local new_app_name="${2? Missing path to create the new app!!!}" + + local new_app_network="${new_app_name}_network" + + local database_hostname="${new_app_name}_postgres" + + local database_data_dir="${host_setup_dir}_${new_app_name}/${database_engine}/data" + + if [ "${port_map}" = ":" ]; then + local port_map="${app_port_map}" + fi + + if [ -z "${container_username}" ]; then + local container_username="${app_username}" + fi + + Start_Or_Attach_To_App_Container \ + "${image_name}" \ + "${erlang_version}" \ + "${elixir_version}" \ + "${phoenix_version}" \ + "${dockerfile}" \ + "${APP_NAME}" \ + "${app_network}" \ + "${app_container_name}" \ + "${container_username}" \ + "${port_map}" \ + "${mix_env}" \ + "${env_file}" \ + "${background_mode}" \ + "${host_setup_dir}" \ + "${build_path}" \ + "${run_command}" \ + ${@} + + # Pinning defaults to be used each time we run the Elixir Docker Stack + echo "elixir_version=${elixir_version}" > "${new_app_name}/${stack_defaults_file}" + echo "dockerfile=${dockerfile}" >> "${new_app_name}/${stack_defaults_file}" + + case "${1:-}" in + phx.new | phoenix.new ) + echo "phoenix_version=${phoenix_version}" >> "${new_app_name}/${stack_defaults_file}" + echo "phoenix_command=${phoenix_command}" >> "${new_app_name}/${stack_defaults_file}" + ;; + esac + + Create_Docker_Network_If_Not_Exists "${new_app_network}" + ${SUDO_PREFIX} docker network rm "${app_network}" + + if Is_App_With_Database "${new_app_name}"; then + + # Pinning defaults to be used each time we run the Elixir Docker Stack + echo "database_image=${database_image}" >> "${new_app_name}/${stack_defaults_file}" + echo "database_user=${database_user}" >> "${new_app_name}/${stack_defaults_file}" + echo "database_data_dir=${database_data_dir}" >> "${new_app_name}/${stack_defaults_file}" + echo "database_command=${database_command}" >> "${new_app_name}/${stack_defaults_file}" + + # Fix the database hostname in the APp configuration file. + sed -i -e "s/hostname: \"localhost\"/hostname: \"${database_hostname}\"/g" ${new_app_name}/config/dev.exs + + Start_Or_Attach_To_Database_Container \ + "${new_app_name}" \ + "${new_app_network}" \ + "${database_image}" \ + "${database_data_dir}" \ + "${database_user}" \ + "${new_app_name}_${database_engine}" \ + "--detach" \ + "${database_command}" + fi + + exit 0 + ;; + + phx.server | phoenix.server ) + Print_Text_With_Label "COMMAND" "phx.server, phoenix.server" "4" + + if [ "${port_map}" = ":" ]; then + local port_map="${app_port_map}" + fi + ;; + + up ) + Print_Text_With_Label "COMMAND" "up" "4" + + shift 1 + + if Is_App_With_Database "${APP_NAME}"; then + + Start_Or_Attach_To_Database_Container \ + "${APP_NAME}" \ + "${app_network}" \ + "${database_image}" \ + "${database_data_dir}" \ + "${database_user}" \ + "${database_container_name}" \ + "--detach" \ + "${database_command}" + fi + + if [ "${port_map}" = ":" ]; then + local port_map="${app_port_map}" + fi + + if [ -z "${container_username}" ]; then + local container_username="${app_username}" + fi + + Start_Dummy_App_Container \ + "${image_name}" \ + "${erlang_version}" \ + "${elixir_version}" \ + "${phoenix_version}" \ + "${dockerfile}" \ + "${APP_NAME}" \ + "${app_network}" \ + "${app_container_name}" \ + "${container_username}" \ + "${port_map}" \ + "${mix_env}" \ + "${env_file}" \ + "${host_setup_dir}" \ + "${build_path}" \ + "${seconds_to_wait_dummy_app_is_ready}" + + + local phoenix_command="${1:-${phoenix_command}}" + + if [ "$#" -ge 1 ]; then + shift 1 + fi + + # we need to set the --cookie and -sname in order to be able to use the + # Observer from another docker container in the same docker network. + # The run command will execute inside the container: + # $ elixir --name video-hup_app@172.0.0.2 --cookie some-long-super-secret -S mix phx.server" + local run_command="elixir-server ${APP_NAME} ${ERLANG_COOKIE} ${phoenix_command}" + + break + ;; + + shell ) + Print_Text_With_Label "COMMAND" "Shell" "4" + + shift 1 + + local run_command=${1:-zsh} + + if [ "$#" -ge 1 ]; then + shift 1 + fi + + break + ;; + + esac + done + + + ############################################################################ + # EXECUTION + ############################################################################ + + if [ -z "${container_username}" ]; then + local container_username="${app_username}" + fi + + Start_Or_Attach_To_App_Container \ + "${image_name}" \ + "${erlang_version}" \ + "${elixir_version}" \ + "${phoenix_version}" \ + "${dockerfile}" \ + "${APP_NAME}" \ + "${app_network}" \ + "${app_container_name}" \ + "${container_username}" \ + "${port_map}" \ + "${mix_env}" \ + "${env_file}" \ + "${background_mode}" \ + "${host_setup_dir}" \ + "${build_path}" \ + "${run_command}" \ + ${@} + } + +Main "${@}" diff --git a/bin/erl b/bin/erl new file mode 120000 index 0000000..54d582f --- /dev/null +++ b/bin/erl @@ -0,0 +1 @@ +elixir \ No newline at end of file diff --git a/bin/iex b/bin/iex new file mode 120000 index 0000000..54d582f --- /dev/null +++ b/bin/iex @@ -0,0 +1 @@ +elixir \ No newline at end of file diff --git a/bin/mix b/bin/mix new file mode 120000 index 0000000..54d582f --- /dev/null +++ b/bin/mix @@ -0,0 +1 @@ +elixir \ No newline at end of file diff --git a/bin/test-sudo b/bin/test-sudo new file mode 100755 index 0000000..a136237 --- /dev/null +++ b/bin/test-sudo @@ -0,0 +1,26 @@ +#!/bin/sh + +set -eu + +# One Liner for testing in shell: +# → if sudo -h > /dev/null 2>&1 ; then echo 'Sudo is enabled.' ; else echo 'Sudo is not enabled' ; fi +Sudo_Exists() +{ + if sudo -h > /dev/null 2>&1; then + return 0 # sudo exists + fi + + return 1 # sudo doesn't exist +} + +Sudo_Prefix() +{ + if Sudo_Exists; then + echo 'sudo' + return + fi + + echo "" +} + +echo $(Sudo_Prefix) diff --git a/docker/build/alpine.Dockerfile b/docker/build/alpine.Dockerfile new file mode 100644 index 0000000..f774c19 --- /dev/null +++ b/docker/build/alpine.Dockerfile @@ -0,0 +1,135 @@ +ARG ELIXIR_VERSION=1.8 + +FROM elixir:${ELIXIR_VERSION}-alpine + +ARG CONTAINER_USER="elixir" +ARG CONTAINER_UID="1000" +ARG CONTAINER_GID="1000" +ARG DISPLAY=":0" +ARG OH_MY_ZSH_THEME="bira" + +ENV CONTAINER_USER=${CONTAINER_USER} \ + CONTAINER_UID=${CONTAINER_UID} \ + CONTAINER_GID=${CONTAINER_GID} \ + DISPLAY=${DISPLAY} \ + PGDATA=/var/lib/postgresql/data + +COPY ./resources /docker-build-resources + +RUN apk update && \ + apk upgrade && \ + apk add --no-cache \ + ca-certificates \ + curl \ + git \ + zsh \ + firefox-esr \ + python \ + python-dev \ + py-pip \ + nodejs \ + npm \ + postgresql \ + postgresql-client \ + postgresql-contrib \ + postgresql-libs \ + postgresql-dev \ + gcc \ + make \ + musl-dev \ + inotify-tools \ + ttf-freefont \ + libcanberra-gtk3 \ + mesa-gl \ + mesa-dri-intel \ + dbus \ + erlang-xmerl \ + erlang-dialyzer \ + erlang-sasl \ + erlang-runtime-tools \ + erlang-ssh \ + erlang-erl-docgen \ + erlang-eunit \ + erlang-inets \ + erlang-tools \ + erlang-snmp \ + erlang-et \ + erlang-dev \ + erlang-wx \ + erlang-debugger \ + erlang-jinterface \ + erlang-asn1 \ + erlang-hipe \ + erlang-odbc \ + erlang-otp-mibs \ + erlang-reltool \ + erlang-crypto \ + erlang-common-test \ + erlang-ssl \ + erlang-mnesia \ + erlang-os-mon \ + erlang-erts \ + erlang-public-key \ + erlang-observer \ + erlang-edoc \ + erlang-eldap \ + erlang-megaco \ + erlang-diameter \ + erlang-wx && \ + + # https://elixirforum.com/t/observer-start-is-not-working-on-ubuntu/6018/21?u=exadra37 + /docker-build-resources/scripts/elixir/observer/fix-dependencies.sh && \ + + pip install psycopg2 pgcli && \ + + printf "fs.inotify.max_user_watches=524288\n" > /etc/sysctl.d/01-exadra37.conf && \ + + addgroup \ + -g "${CONTAINER_GID}" \ + -S "${CONTAINER_USER}" && \ + adduser \ + -s /bin/zsh \ + -u "${CONTAINER_UID}" \ + -G "${CONTAINER_USER}" \ + -h /home/"${CONTAINER_USER}" \ + -D "${CONTAINER_USER}" && \ + + mkdir -p "${PGDATA}" /run/postgresql && \ + chown -R "${CONTAINER_USER}":"${CONTAINER_USER}" "${PGDATA}/.." && \ + chown -R "${CONTAINER_USER}":"${CONTAINER_USER}" /run/postgresql/ && \ + addgroup "${CONTAINER_USER}" postgres && \ + + sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)" && \ + cp -v /root/.zshrc /home/"${CONTAINER_USER}"/.zshrc && \ + cp -rv /root/.oh-my-zsh /home/"${CONTAINER_USER}"/.oh-my-zsh && \ + sed -i "s/\/root/\/home\/${CONTAINER_USER}/g" /home/"${CONTAINER_USER}"/.zshrc && \ + sed -i s/ZSH_THEME=\"robbyrussell\"/ZSH_THEME=\"${OH_MY_ZSH_THEME}\"/g /home/${CONTAINER_USER}/.zshrc && \ + + mkdir /home/"${CONTAINER_USER}"/workspace && \ + chown -R "${CONTAINER_USER}":"${CONTAINER_USER}" /home/"${CONTAINER_USER}" + +USER "${CONTAINER_USER}" + +ARG PHOENIX_VERSION=1.4.0 +ARG PHOENIX_INSTALL_FROM="hex phx_new ${PHOENIX_VERSION}" + +# This commands will run under user defined above +RUN zsh -c "eval 'initdb --username=postgres --pwfile=<(echo postgres)'" && \ + + # https://docs.docker.com/engine/examples/postgresql_service/ + pg_ctl start && \ + createdb --username postgres --owner postgres testapp_dev && \ + createdb --username postgres --owner postgres testapp_test && \ + createdb --username postgres --owner postgres testapp_prod && \ + + mix local.hex --force && \ + mix local.rebar --force && \ + mix archive.install --force ${PHOENIX_INSTALL_FROM} + +VOLUME ["/var/log/postgresql", "/var/lib/postgresql"] + +EXPOSE 5432 + +WORKDIR "/home/${CONTAINER_USER}/workspace" + +CMD ["elixir"] diff --git a/docker/build/debian.Dockerfile b/docker/build/debian.Dockerfile new file mode 100644 index 0000000..4d36399 --- /dev/null +++ b/docker/build/debian.Dockerfile @@ -0,0 +1,95 @@ +ARG DOCKER_ELIXIR_VERSION=1.8 + +FROM elixir:${DOCKER_ELIXIR_VERSION} + +ARG CONTAINER_USER_NAME="elixir" +ARG CONTAINER_UID="1000" +ARG CONTAINER_GID="1000" +ARG DISPLAY=":0" +ARG OH_MY_ZSH_THEME="bira" + +ARG LANGUAGE_CODE="en" +ARG COUNTRY_CODE="GB" +ARG ENCODING="UTF-8" +ARG LOCALE_STRING="${LANGUAGE_CODE}_${COUNTRY_CODE}" +ARG LOCALIZATION="${LOCALE_STRING}.${ENCODING}" + +ARG POSTGRES_VERSION=11 + +ARG SUBLIME_BUILD=latest +ARG RESOURCES_DIR="/docker-build-resources" + +ARG MIX_ENV=dev +ARG PHOENIX_VERSION=1.4.3 +ARG NODE_VERSION=10 + +ENV DEBIAN_FRONTEND="noninteractive" \ + NO_AT_BRIDGE=1 \ + LANG="${LOCALIZATION}" \ + LC_ALL="${LOCALIZATION}" \ + LANGUAGE="${LOCALE_STRING}:${LANGUAGE_CODE}" \ + WORKSPACE_PATH="/home/${CONTAINER_USER_NAME}/workspace" \ + CONTAINER_HOME="/home/${CONTAINER_USER_NAME}" \ + CONTAINER_BIN_PATH="/home/${CONTAINER_USER_NAME}/bin" \ + CONTAINER_UID=${CONTAINER_UID} \ + CONTAINER_GID=${CONTAINER_GID} \ + DISPLAY=${DISPLAY} \ + MIX_ENV=${MIX_ENV} + +ENV PATH="${CONTAINER_BIN_PATH}":"${POSTGRES_BIN_PATH}":${PATH} + +COPY ./resources /docker-build-resources + +RUN \ + apt update && \ + apt -y upgrade && \ + apt -y -q install --no-install-recommends \ + ca-certificates \ + zsh \ + curl \ + less \ + git \ + libcanberra-gtk-module && \ + + apt -y -q -f install && \ + + useradd -m -u "${CONTAINER_UID}" -s /usr/bin/zsh "${CONTAINER_USER_NAME}" && \ + + chown --recursive "${CONTAINER_USER_NAME}":"${CONTAINER_USER_NAME}" "${RESOURCES_DIR}" && \ + + su "${CONTAINER_USER_NAME}" -c "sh -c 'mkdir -p ${CONTAINER_BIN_PATH}'" && \ + su "${CONTAINER_USER_NAME}" -c "sh -c 'cp -r ${RESOURCES_DIR}/scripts/elixir/bin/* ${CONTAINER_BIN_PATH}'" && \ + + "${RESOURCES_DIR}"/scripts/debian/install-locales.sh \ + "${LOCALIZATION}" \ + "${ENCODING}" && \ + + "${RESOURCES_DIR}"/scripts/debian/install-nodejs.sh "${NODE_VERSION}" && \ + + "${RESOURCES_DIR}"/scripts/debian/install-pgcli.sh && \ + + "${RESOURCES_DIR}"/scripts/debian/install-inotify-tools.sh && \ + + "${RESOURCES_DIR}"/scripts/install-oh-my-zsh.sh \ + "${CONTAINER_HOME}" \ + "${OH_MY_ZSH_THEME}" && \ + + "${RESOURCES_DIR}"/scripts/create-workspace-dir.sh \ + "${WORKSPACE_PATH}" \ + "${CONTAINER_USER_NAME}" && \ + + apt auto-remove && \ + apt clean && \ + rm -rf /var/lib/apt/lists/* + +USER "${CONTAINER_USER_NAME}" + +WORKDIR "${CONTAINER_HOME}" + +RUN "${RESOURCES_DIR}"/scripts/elixir/phoenix/install.sh "${PHOENIX_VERSION}" + +VOLUME ["/var/log/postgresql", "/var/lib/postgresql", "/home/elixir/.config/sublime-text-3"] + +WORKDIR "${WORKSPACE_PATH}" + +CMD ["elixir"] diff --git a/docker/build/debian.esl.Dockerfile b/docker/build/debian.esl.Dockerfile new file mode 100644 index 0000000..768b2fb --- /dev/null +++ b/docker/build/debian.esl.Dockerfile @@ -0,0 +1,119 @@ +ARG OS_TAG=stretch + +FROM debian:${OS_TAG} + +ARG DOCKER_ERLANG_VERSION=21.3.3-1 +ARG DOCKER_ELIXIR_VERSION=1.8.1-2 + +ARG CONTAINER_USER_NAME="elixir" +ARG CONTAINER_UID="1000" +ARG CONTAINER_GID="1000" +ARG DISPLAY=":0" +ARG OH_MY_ZSH_THEME="bira" + +ARG LANGUAGE_CODE="en" +ARG COUNTRY_CODE="GB" +ARG ENCODING="UTF-8" +ARG LOCALE_STRING="${LANGUAGE_CODE}_${COUNTRY_CODE}" +ARG LOCALIZATION="${LOCALE_STRING}.${ENCODING}" + +ARG POSTGRES_VERSION=11 + +ARG SUBLIME_BUILD=latest +ARG RESOURCES_DIR="/docker-build-resources" + +ARG PHOENIX_VERSION=1.4.3 +ARG PHOENIX_INSTALL_FROM="hex phx_new ${PHOENIX_VERSION}" +ARG NODE_VERSION=10 + +ARG ERLANG_DOWNLOAD_URL=https://packages.erlang-solutions.com/erlang/esl-erlang/FLAVOUR_1_general/esl-erlang_"${DOCKER_ERLANG_VERSION}"~debian~stretch_amd64.deb +ARG ELIXIR_DOWNLOAD_URL=https://packages.erlang-solutions.com/erlang/elixir/FLAVOUR_2_download/elixir_"${DOCKER_ELIXIR_VERSION}"~debian~stretch_amd64.deb + +ENV DEBIAN_FRONTEND="noninteractive" \ + NO_AT_BRIDGE=1 \ + LANG="${LOCALIZATION}" \ + LC_ALL="${LOCALIZATION}" \ + LANGUAGE="${LOCALE_STRING}:${LANGUAGE_CODE}" \ + WORKSPACE_PATH="/home/${CONTAINER_USER_NAME}/workspace" \ + CONTAINER_HOME="/home/${CONTAINER_USER_NAME}" \ + CONTAINER_BIN_PATH="/home/${CONTAINER_USER_NAME}/bin" \ + CONTAINER_UID=${CONTAINER_UID} \ + CONTAINER_GID=${CONTAINER_GID} \ + DISPLAY=${DISPLAY} \ + PGDATA=/var/lib/postgresql/"${POSTGRES_VERSION}"/main \ + POSTGRES_BIN_PATH=/usr/lib/postgresql/"${POSTGRES_VERSION}"/bin \ + PGUSER=elixir + +ENV PATH="${CONTAINER_BIN_PATH}":"${POSTGRES_BIN_PATH}":${PATH} + +COPY ./resources /docker-build-resources + +RUN apt update && \ + apt -y upgrade && \ + apt -y -q install --no-install-recommends \ + build-essential \ + ca-certificates \ + zsh \ + curl \ + less \ + git \ + libcanberra-gtk-module \ + + procps \ + libncurses5 \ + libwxbase3.0-0v5 \ + libwxgtk3.0-0v5 \ + libsctp1 && \ + + apt -y -f install && \ + + useradd -m -u "${CONTAINER_UID}" -s /usr/bin/zsh "${CONTAINER_USER_NAME}" && \ + + chown --recursive "${CONTAINER_USER_NAME}":"${CONTAINER_USER_NAME}" "${RESOURCES_DIR}" && \ + + su "${CONTAINER_USER_NAME}" -c "sh -c 'mkdir -p ${CONTAINER_BIN_PATH}'" && \ + su "${CONTAINER_USER_NAME}" -c "sh -c 'cp -r ${RESOURCES_DIR}/scripts/elixir/bin/* ${CONTAINER_BIN_PATH}'" && \ + + curl -o esl.deb "${ERLANG_DOWNLOAD_URL}" && \ + dpkg -i esl.deb && \ + rm -f esl.deb && \ + + printf "\nELIXIR DOWNLOAD URK: ${ELIXIR_DOWNLOAD_URL}\n" && \ + + curl -fsSL -o elixir.deb "${ELIXIR_DOWNLOAD_URL}" && \ + dpkg -i elixir.deb && \ + rm -f elixir.deb && \ + + "${RESOURCES_DIR}"/scripts/debian/install-locales.sh \ + "${LOCALIZATION}" \ + "${ENCODING}" && \ + + "${RESOURCES_DIR}"/scripts/debian/install-nodejs.sh "${NODE_VERSION}" && \ + + "${RESOURCES_DIR}"/scripts/debian/install-pgcli.sh && \ + + "${RESOURCES_DIR}"/scripts/debian/install-inotify-tools.sh && \ + + "${RESOURCES_DIR}"/scripts/install-oh-my-zsh.sh \ + "${CONTAINER_HOME}" \ + "${OH_MY_ZSH_THEME}" && \ + + "${RESOURCES_DIR}"/scripts/create-workspace-dir.sh \ + "${WORKSPACE_PATH}" \ + "${CONTAINER_USER_NAME}" && \ + + apt auto-remove && \ + apt clean && \ + rm -rf /var/lib/apt/lists/* + +USER "${CONTAINER_USER_NAME}" + +WORKDIR "${CONTAINER_HOME}" + +RUN "${RESOURCES_DIR}"/scripts/elixir/phoenix/install.sh "${PHOENIX_VERSION}" + +VOLUME ["/var/log/postgresql", "/var/lib/postgresql", "/home/elixir/.config/sublime-text-3"] + +WORKDIR "${WORKSPACE_PATH}" + +CMD ["elixir"] diff --git a/docker/build/debian.git.branch.Dockerfile b/docker/build/debian.git.branch.Dockerfile new file mode 100644 index 0000000..59e918a --- /dev/null +++ b/docker/build/debian.git.branch.Dockerfile @@ -0,0 +1,159 @@ +FROM debian:stretch + +ARG DOCKER_ERLANG_VERSION=21.3.4 +ARG DOCKER_ELIXIR_VERSION=1.8.1 +ARG ELIXIR_GIT_BRANCH="${DOCKER_ELIXIR_VERSION}" + +ARG CONTAINER_USER_NAME="elixir" +ARG CONTAINER_UID="1000" +ARG CONTAINER_GID="1000" +ARG DISPLAY=":0" +ARG OH_MY_ZSH_THEME="bira" + +ARG LANGUAGE_CODE="en" +ARG COUNTRY_CODE="GB" +ARG ENCODING="UTF-8" +ARG LOCALE_STRING="${LANGUAGE_CODE}_${COUNTRY_CODE}" +ARG LOCALIZATION="${LOCALE_STRING}.${ENCODING}" + +ARG POSTGRES_VERSION=11 + +ARG SUBLIME_BUILD=latest +ARG RESOURCES_DIR="/docker-build-resources" + +ARG PHOENIX_VERSION=1.4.3 +ARG PHOENIX_INSTALL_FROM="hex phx_new ${PHOENIX_VERSION}" +ARG NODE_VERSION=10 + +ENV OTP_VERSION="${DOCKER_ERLANG_VERSION}" + +ARG OTP_DOWNLOAD_URL="https://github.com/erlang/otp/archive/OTP-${OTP_VERSION}.tar.gz" +ARG OTP_DOWNLOAD_SHA256="1af7c01e80d04423c14449fcb7c5f3b11e0375fe42d01b088ccef4cbcb733c3a" + +ARG ELIXIR_INSTALL_DIR=/usr/local/src/elixir +ARG ELIXIR_BIN_PATH="${ELIXIR_INSTALL_DIR}/bin" + +ENV DEBIAN_FRONTEND="noninteractive" \ + NO_AT_BRIDGE=1 \ + LANG="${LOCALIZATION}" \ + LC_ALL="${LOCALIZATION}" \ + LANGUAGE="${LOCALE_STRING}:${LANGUAGE_CODE}" \ + WORKSPACE_PATH="/home/${CONTAINER_USER_NAME}/workspace" \ + CONTAINER_HOME="/home/${CONTAINER_USER_NAME}" \ + CONTAINER_BIN_PATH="/home/${CONTAINER_USER_NAME}/bin" \ + CONTAINER_UID=${CONTAINER_UID} \ + CONTAINER_GID=${CONTAINER_GID} \ + DISPLAY=${DISPLAY} \ + PGDATA=/var/lib/postgresql/"${POSTGRES_VERSION}"/main \ + POSTGRES_BIN_PATH=/usr/lib/postgresql/"${POSTGRES_VERSION}"/bin \ + PGUSER=elixir + +ENV PATH="${ELIXIR_BIN_PATH}":"${CONTAINER_BIN_PATH}":"${POSTGRES_BIN_PATH}":"${PATH}" + +ARG BUILD_DEPS=' \ + autoconf \ + dpkg-dev \ + gcc \ + g++ \ + make \ + libncurses-dev \ + unixodbc-dev \ + libssl-dev \ + libsctp-dev \ + unixodbc-dev \ + libwxgtk3.0-dev \ +' + +COPY ./resources /docker-build-resources + +# We'll install the build dependencies, and purge them on the last step to make +# sure our final image contains only what we've just built: +RUN \ + fetchDeps=' \ + build-essential \ + curl \ + zsh \ + git \ + libcanberra-gtk-module \ + ca-certificates' \ + && runtimeDeps=' \ + procps \ + libncurses5 \ + libwxbase3.0-0v5 \ + libwxgtk3.0-0v5 \ + libodbc1 \ + libssl1.1 \ + libsctp1 \ + ' \ + && apt update \ + && apt install -y -q --no-install-recommends \ + $fetchDeps \ + $runtimeDeps \ + $BUILD_DEPS && \ + + useradd -m -u "${CONTAINER_UID}" -s /usr/bin/zsh "${CONTAINER_USER_NAME}" && \ + + chown --recursive "${CONTAINER_USER_NAME}":"${CONTAINER_USER_NAME}" "${RESOURCES_DIR}" && \ + + su "${CONTAINER_USER_NAME}" -c "sh -c 'mkdir -p ${CONTAINER_BIN_PATH}'" && \ + su "${CONTAINER_USER_NAME}" -c "sh -c 'cp -r ${RESOURCES_DIR}/scripts/elixir/bin/* ${CONTAINER_BIN_PATH}'" && \ + + "${RESOURCES_DIR}"/scripts/debian/install-locales.sh \ + "${LOCALIZATION}" \ + "${ENCODING}" && \ + + "${RESOURCES_DIR}"/scripts/debian/install-nodejs.sh "${NODE_VERSION}" && \ + + "${RESOURCES_DIR}"/scripts/debian/install-pgcli.sh && \ + + "${RESOURCES_DIR}"/scripts/debian/install-inotify-tools.sh && \ + + "${RESOURCES_DIR}"/scripts/install-oh-my-zsh.sh \ + "${CONTAINER_HOME}" \ + "${OH_MY_ZSH_THEME}" && \ + + "${RESOURCES_DIR}"/scripts/create-workspace-dir.sh \ + "${WORKSPACE_PATH}" \ + "${CONTAINER_USER_NAME}" && \ + + printf "\nOPT_DOWNLOAD_URL: ${OTP_DOWNLOAD_URL}\n" && \ + + curl -fSL -o otp-src.tar.gz "$OTP_DOWNLOAD_URL" && \ + #echo "$OTP_DOWNLOAD_SHA256 otp-src.tar.gz" | sha256sum -c - && \ + export ERL_TOP="/usr/src/otp_src_${OTP_VERSION%%@*}" && \ + mkdir -vp $ERL_TOP && \ + tar -xzf otp-src.tar.gz -C $ERL_TOP --strip-components=1 && \ + rm otp-src.tar.gz && \ + ( cd $ERL_TOP && \ + ./otp_build autoconf && \ + gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)" && \ + ./configure --build="$gnuArch" && \ + make -j$(nproc) && \ + make install ) && \ + find /usr/local -name examples | xargs rm -rf && \ + rm -rf $ERL_TOP + +RUN \ + printf "\ELIXIR_INSTALL_DIR: ${ELIXIR_INSTALL_DIR}\n" && \ + printf "\ELIXIR_GIT_BRANCH: ${ELIXIR_GIT_BRANCH}\n" && \ + + mkdir -p "${ELIXIR_INSTALL_DIR}" && \ + cd "${ELIXIR_INSTALL_DIR}" && \ + git clone --branch "${ELIXIR_GIT_BRANCH}" https://github.com/elixir-lang/elixir.git . && \ + make clean test && \ + + # CLEANUP + apt-get purge -y --auto-remove $BUILD_DEPS && \ + rm -rf /var/lib/apt/lists/* + +USER "${CONTAINER_USER_NAME}" + +WORKDIR "${CONTAINER_HOME}" + +RUN "${RESOURCES_DIR}"/scripts/elixir/phoenix/install.sh "${PHOENIX_VERSION}" + +VOLUME ["/var/log/postgresql", "/var/lib/postgresql", "/home/elixir/.config/sublime-text-3"] + +WORKDIR "${WORKSPACE_PATH}" + +CMD ["elixir"] diff --git a/docker/build/debian.git.release.Dockerfile b/docker/build/debian.git.release.Dockerfile new file mode 100644 index 0000000..4a4de3d --- /dev/null +++ b/docker/build/debian.git.release.Dockerfile @@ -0,0 +1,161 @@ +FROM debian:stretch + +ARG DOCKER_ERLANG_VERSION=21.3.4 +ARG DOCKER_ELIXIR_VERSION=1.8.1 + +ARG CONTAINER_USER_NAME="elixir" +ARG CONTAINER_UID="1000" +ARG CONTAINER_GID="1000" +ARG DISPLAY=":0" +ARG OH_MY_ZSH_THEME="bira" + +ARG LANGUAGE_CODE="en" +ARG COUNTRY_CODE="GB" +ARG ENCODING="UTF-8" +ARG LOCALE_STRING="${LANGUAGE_CODE}_${COUNTRY_CODE}" +ARG LOCALIZATION="${LOCALE_STRING}.${ENCODING}" + +ARG POSTGRES_VERSION=11 + +ARG SUBLIME_BUILD=latest +ARG RESOURCES_DIR="/docker-build-resources" + +ARG PHOENIX_VERSION=1.4.3 +ARG PHOENIX_INSTALL_FROM="hex phx_new ${PHOENIX_VERSION}" +ARG NODE_VERSION=10 + +ENV ELIXIR_VERSION="v${DOCKER_ELIXIR_VERSION}" +ENV OTP_VERSION="${DOCKER_ERLANG_VERSION}" + +ARG OTP_DOWNLOAD_URL="https://github.com/erlang/otp/archive/OTP-${OTP_VERSION}.tar.gz" +ARG OTP_DOWNLOAD_SHA256="1af7c01e80d04423c14449fcb7c5f3b11e0375fe42d01b088ccef4cbcb733c3a" + +ARG ELIXIR_DOWNLOAD_URL="https://github.com/elixir-lang/elixir/archive/${ELIXIR_VERSION}.tar.gz" +ARG ELIXIR_DOWNLOAD_SHA256="de8c636ea999392496ccd9a204ccccbc8cb7f417d948fd12692cda2bd02d9822" + +ENV DEBIAN_FRONTEND="noninteractive" \ + NO_AT_BRIDGE=1 \ + LANG="${LOCALIZATION}" \ + LC_ALL="${LOCALIZATION}" \ + LANGUAGE="${LOCALE_STRING}:${LANGUAGE_CODE}" \ + WORKSPACE_PATH="/home/${CONTAINER_USER_NAME}/workspace" \ + CONTAINER_HOME="/home/${CONTAINER_USER_NAME}" \ + CONTAINER_BIN_PATH="/home/${CONTAINER_USER_NAME}/bin" \ + CONTAINER_UID=${CONTAINER_UID} \ + CONTAINER_GID=${CONTAINER_GID} \ + DISPLAY=${DISPLAY} \ + PGDATA=/var/lib/postgresql/"${POSTGRES_VERSION}"/main \ + POSTGRES_BIN_PATH=/usr/lib/postgresql/"${POSTGRES_VERSION}"/bin \ + PGUSER=elixir + +ENV PATH="${CONTAINER_BIN_PATH}":"${POSTGRES_BIN_PATH}":${PATH} + +ARG BUILD_DEPS=' \ + autoconf \ + dpkg-dev \ + gcc \ + g++ \ + make \ + libncurses-dev \ + unixodbc-dev \ + libssl-dev \ + libsctp-dev \ + unixodbc-dev \ + libwxgtk3.0-dev \ +' + +COPY ./resources /docker-build-resources + +# We'll install the build dependencies, and purge them on the last step to make +# sure our final image contains only what we've just built: +RUN \ + fetchDeps=' \ + build-essential \ + curl \ + zsh \ + git \ + libcanberra-gtk-module \ + ca-certificates' \ + && runtimeDeps=' \ + procps \ + libncurses5 \ + libwxbase3.0-0v5 \ + libwxgtk3.0-0v5 \ + libodbc1 \ + libssl1.1 \ + libsctp1 \ + ' \ + && apt update \ + && apt install -y -q --no-install-recommends \ + $fetchDeps \ + $runtimeDeps \ + $BUILD_DEPS && \ + + useradd -m -u "${CONTAINER_UID}" -s /usr/bin/zsh "${CONTAINER_USER_NAME}" && \ + + chown --recursive "${CONTAINER_USER_NAME}":"${CONTAINER_USER_NAME}" "${RESOURCES_DIR}" && \ + + su "${CONTAINER_USER_NAME}" -c "sh -c 'mkdir -p ${CONTAINER_BIN_PATH}'" && \ + su "${CONTAINER_USER_NAME}" -c "sh -c 'cp -r ${RESOURCES_DIR}/scripts/elixir/bin/* ${CONTAINER_BIN_PATH}'" && \ + + "${RESOURCES_DIR}"/scripts/debian/install-locales.sh \ + "${LOCALIZATION}" \ + "${ENCODING}" && \ + + "${RESOURCES_DIR}"/scripts/debian/install-nodejs.sh "${NODE_VERSION}" && \ + + "${RESOURCES_DIR}"/scripts/debian/install-pgcli.sh && \ + + "${RESOURCES_DIR}"/scripts/debian/install-inotify-tools.sh && \ + + "${RESOURCES_DIR}"/scripts/install-oh-my-zsh.sh \ + "${CONTAINER_HOME}" \ + "${OH_MY_ZSH_THEME}" && \ + + "${RESOURCES_DIR}"/scripts/create-workspace-dir.sh \ + "${WORKSPACE_PATH}" \ + "${CONTAINER_USER_NAME}" && \ + + printf "\nOPT_DOWNLOAD_URL: ${OTP_DOWNLOAD_URL}\n" && \ + + curl -fSL -o otp-src.tar.gz "$OTP_DOWNLOAD_URL" && \ + #echo "$OTP_DOWNLOAD_SHA256 otp-src.tar.gz" | sha256sum -c - && \ + export ERL_TOP="/usr/src/otp_src_${OTP_VERSION%%@*}" && \ + mkdir -vp $ERL_TOP && \ + tar -xzf otp-src.tar.gz -C $ERL_TOP --strip-components=1 && \ + rm otp-src.tar.gz && \ + ( cd $ERL_TOP && \ + ./otp_build autoconf && \ + gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)" && \ + ./configure --build="$gnuArch" && \ + make -j$(nproc) && \ + make install ) && \ + find /usr/local -name examples | xargs rm -rf && \ + rm -rf $ERL_TOP + +RUN \ + printf "\nELIXIR_DOWNLOAD_URL: ${ELIXIR_DOWNLOAD_URL}\n" && \ + + curl -fSL -o elixir-src.tar.gz $ELIXIR_DOWNLOAD_URL && \ + #echo "$ELIXIR_DOWNLOAD_SHA256 elixir-src.tar.gz" | sha256sum -c - && \ + mkdir -p /usr/local/src/elixir && \ + tar -xzC /usr/local/src/elixir --strip-components=1 -f elixir-src.tar.gz && \ + rm elixir-src.tar.gz && \ + cd /usr/local/src/elixir && \ + make install clean && \ + + #apt-get purge -y --auto-remove $BUILD_DEPS && \ + rm -rf /var/lib/apt/lists/* + + +USER "${CONTAINER_USER_NAME}" + +WORKDIR "${CONTAINER_HOME}" + +RUN "${RESOURCES_DIR}"/scripts/elixir/phoenix/install.sh "${PHOENIX_VERSION}" + +VOLUME ["/var/log/postgresql", "/var/lib/postgresql", "/home/elixir/.config/sublime-text-3"] + +WORKDIR "${WORKSPACE_PATH}" + +CMD ["elixir"] diff --git a/docker/build/debian.slim.Dockerfile b/docker/build/debian.slim.Dockerfile new file mode 100644 index 0000000..47583bb --- /dev/null +++ b/docker/build/debian.slim.Dockerfile @@ -0,0 +1,97 @@ +ARG DOCKER_ELIXIR_VERSION=1.8 + +FROM elixir:${DOCKER_ELIXIR_VERSION}-slim + +ARG CONTAINER_USER_NAME="elixir" +ARG CONTAINER_UID="1000" +ARG CONTAINER_GID="1000" +ARG DISPLAY=":0" +ARG OH_MY_ZSH_THEME="bira" + +ARG LANGUAGE_CODE="en" +ARG COUNTRY_CODE="GB" +ARG ENCODING="UTF-8" +ARG LOCALE_STRING="${LANGUAGE_CODE}_${COUNTRY_CODE}" +ARG LOCALIZATION="${LOCALE_STRING}.${ENCODING}" + +ARG POSTGRES_VERSION=11 + +ARG SUBLIME_BUILD=latest +ARG RESOURCES_DIR="/docker-build-resources" + +ARG MIX_ENV=dev +ARG PHOENIX_VERSION=1.4.3 +ARG NODE_VERSION=10 + +ENV DEBIAN_FRONTEND="noninteractive" \ + NO_AT_BRIDGE=1 \ + LANG="${LOCALIZATION}" \ + LC_ALL="${LOCALIZATION}" \ + LANGUAGE="${LOCALE_STRING}:${LANGUAGE_CODE}" \ + WORKSPACE_PATH="/home/${CONTAINER_USER_NAME}/workspace" \ + CONTAINER_HOME="/home/${CONTAINER_USER_NAME}" \ + CONTAINER_BIN_PATH="/home/${CONTAINER_USER_NAME}/bin" \ + CONTAINER_UID=${CONTAINER_UID} \ + CONTAINER_GID=${CONTAINER_GID} \ + DISPLAY=${DISPLAY} \ + MIX_ENV=${MIX_ENV} + +ENV PATH="${CONTAINER_BIN_PATH}":"${POSTGRES_BIN_PATH}":${PATH} + +COPY ./resources /docker-build-resources + +RUN \ + apt update && \ + apt -y upgrade && \ + apt -y -q install --no-install-recommends \ + ca-certificates \ + zsh \ + curl \ + less \ + build-essential \ + erlang-dev \ + git && \ + apt -y -q -f install && \ + + useradd -m -u "${CONTAINER_UID}" -s /usr/bin/zsh "${CONTAINER_USER_NAME}" && \ + + chown --recursive "${CONTAINER_USER_NAME}":"${CONTAINER_USER_NAME}" "${RESOURCES_DIR}" && \ + + su "${CONTAINER_USER_NAME}" -c "sh -c 'mkdir -p ${CONTAINER_BIN_PATH}'" && \ + su "${CONTAINER_USER_NAME}" -c "sh -c 'cp -r ${RESOURCES_DIR}/scripts/elixir/bin/* ${CONTAINER_BIN_PATH}'" && \ + + "${RESOURCES_DIR}"/scripts/debian/install-locales.sh \ + "${LOCALIZATION}" \ + "${ENCODING}" && \ + + "${RESOURCES_DIR}"/scripts/elixir/observer/fix-dependencies.sh && \ + + "${RESOURCES_DIR}"/scripts/debian/install-nodejs.sh "${NODE_VERSION}" && \ + + "${RESOURCES_DIR}"/scripts/debian/install-pgcli.sh && \ + + "${RESOURCES_DIR}"/scripts/debian/install-inotify-tools.sh && \ + + "${RESOURCES_DIR}"/scripts/install-oh-my-zsh.sh \ + "${CONTAINER_HOME}" \ + "${OH_MY_ZSH_THEME}" && \ + + "${RESOURCES_DIR}"/scripts/create-workspace-dir.sh \ + "${WORKSPACE_PATH}" \ + "${CONTAINER_USER_NAME}" && \ + + apt auto-remove && \ + apt clean && \ + rm -rf /var/lib/apt/lists/* + +USER "${CONTAINER_USER_NAME}" + +WORKDIR "${CONTAINER_HOME}" + +RUN "${RESOURCES_DIR}"/scripts/elixir/phoenix/install.sh "${PHOENIX_VERSION}" + +VOLUME ["/var/log/postgresql", "/var/lib/postgresql", "/home/elixir/.config/sublime-text-3"] + +WORKDIR "${WORKSPACE_PATH}" + +CMD ["elixir"] diff --git a/docker/build/observer-debian.Dockerfile b/docker/build/observer-debian.Dockerfile new file mode 100644 index 0000000..dbb3416 --- /dev/null +++ b/docker/build/observer-debian.Dockerfile @@ -0,0 +1,61 @@ +ARG DOCKER_ELIXIR_VERSION=latest + +FROM elixir:${DOCKER_ELIXIR_VERSION} + +ARG CONTAINER_USER_NAME="observer" +ARG CONTAINER_UID="1000" +ARG CONTAINER_GID="1000" +ARG DISPLAY=":0" +ARG OH_MY_ZSH_THEME="bira" + +ENV DEBIAN_FRONTEND="noninteractive" \ + NO_AT_BRIDGE=1 \ + DISPLAY=${DISPLAY} \ + CONTAINER_USER_NAME="${CONTAINER_USER_NAME}" \ + CONTAINER_HOME="/home/${CONTAINER_USER_NAME}" \ + CONTAINER_BIN_PATH="/home/${CONTAINER_USER_NAME}/bin" \ + CONTAINER_UID=${CONTAINER_UID} \ + CONTAINER_GID=${CONTAINER_GID} \ + RESOURCES_DIR=/docker-build-resources \ + WORKSPACE_PATH="/home/${CONTAINER_USER_NAME}/workspace" + +ENV PATH="${CONTAINER_BIN_PATH}":${PATH} + +COPY ./resources /docker-build-resources + +RUN apt update && \ + apt -y upgrade && \ + apt install -y --no-install-recommends \ + zsh \ + libcanberra-gtk-module && \ + + useradd -m -u "${CONTAINER_UID}" -s /usr/bin/zsh "${CONTAINER_USER_NAME}" && \ + + chown --recursive "${CONTAINER_USER_NAME}":"${CONTAINER_USER_NAME}" "${RESOURCES_DIR}" && \ + + su "${CONTAINER_USER_NAME}" -c "sh -c 'mkdir -p ${CONTAINER_HOME}/.local/share'" && \ + su "${CONTAINER_USER_NAME}" -c "sh -c 'mkdir -p ${CONTAINER_BIN_PATH}'" && \ + su "${CONTAINER_USER_NAME}" -c "sh -c 'cp -r ${RESOURCES_DIR}/scripts/elixir/bin/observer ${CONTAINER_BIN_PATH}'" && \ + su "${CONTAINER_USER_NAME}" -c "sh -c 'cp -r ${RESOURCES_DIR}/scripts/elixir/bin/observer-cli ${CONTAINER_BIN_PATH}'" && \ + + "${RESOURCES_DIR}"/scripts/install-oh-my-zsh.sh \ + "${CONTAINER_HOME}" \ + "${OH_MY_ZSH_THEME}" && \ + + "${RESOURCES_DIR}"/scripts/create-workspace-dir.sh \ + "${WORKSPACE_PATH}" \ + "${CONTAINER_USER_NAME}" + +USER "${CONTAINER_USER_NAME}" + +WORKDIR "${CONTAINER_HOME}" + +ENV PATH="${CONTAINER_HOME}"/observer_cli/_build/default/bin:${PATH} + +RUN git clone https://github.com/zhongwencool/observer_cli.git && \ + cd observer_cli && \ + rebar3 escriptize + +WORKDIR "${WORKSPACE_PATH}" + +CMD ["erl", "-hidden", "-run", "observer"] diff --git a/docker/build/resources/custom-ssl/certificates/.gitignore b/docker/build/resources/custom-ssl/certificates/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/docker/build/resources/custom-ssl/certificates/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/docker/build/resources/custom-ssl/trusted-store/android/adb-setup-certificate.sh b/docker/build/resources/custom-ssl/trusted-store/android/adb-setup-certificate.sh new file mode 100755 index 0000000..59fcf20 --- /dev/null +++ b/docker/build/resources/custom-ssl/trusted-store/android/adb-setup-certificate.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +set -eu + +Main() +{ + ############################################################################## + # INPUT + ############################################################################## + + local pem_certificate_file=${1? Missing the PEM certificate file name} + + + ############################################################################## + # EXECUTION + ############################################################################## + + # https://stackoverflow.com/a/48814971/6454622 + local certificate_name=$(openssl x509 -inform PEM -subject_hash_old -in ${pem_certificate_file} | head -1) + + cat "${pem_certificate_file}" > "${certificate_name}" + openssl x509 -inform PEM -text -in "${pem_certificate_file}" -out nul >> "$certificate_name}" + + adb shell mount -o rw,remount,rw /system + adb push "${certificate_name}" /system/etc/security/cacerts/ + adb shell mount -o ro,remount,ro /system +} + +Main "${@}" diff --git a/docker/build/resources/custom-ssl/trusted-store/browsers/add-certificate-to-browser.sh b/docker/build/resources/custom-ssl/trusted-store/browsers/add-certificate-to-browser.sh new file mode 100755 index 0000000..731f97a --- /dev/null +++ b/docker/build/resources/custom-ssl/trusted-store/browsers/add-certificate-to-browser.sh @@ -0,0 +1,59 @@ +#!/bin/sh + +set -eu + +################################################################################ +# Inspired on https://thomas-leister.de/en/how-to-import-ca-root-certificate/ +# +# Script installs root.cert.pem to certificate trust store of applications using +# NSS (e.g. Firefox, Thunderbird, Chromium) +# +# Mozilla uses cert8, Chromium and Chrome use cert9 +# +# Requirement: apt install libnss3-tools +# + +Main() +{ + ############################################################################## + # INPUT + ############################################################################## + + local pem_certificate_file_path="${1? Missing file path for the PEM certificate}" + local certificate_name="${2?Missing Certificate Name}" + local browser_config_dir="${3:-/home/node}" + + + ############################################################################## + # EXECUTION + ############################################################################## + + printf "\n>>> ADDING CERTIFICATE TO BROWSERS TRUSTED STORE <<<\n" + printf "\n--> CERTIFICATE FILE: ${pem_certificate_file_path}\n" + + if [ -f "${pem_certificate_file_path}" ]; then + + apt install -y libnss3-tools + + printf "\n--> CERTIFICATE NAME: ${certificate_name}\n" + printf "\n--> BROWSER CONFIG DIR: ${browser_config_dir} \n" + + # For cert8 (legacy - DBM) - Mozilla + for certificate_database in $(find "${browser_config_dir}" -name "cert8.db"); do + local certificate_dir=$(dirname ${certificate_database}); + certutil -A -n "${certificate_name}" -t "TCu,Cu,Tu" -i "${pem_certificate_file_path}" -d dbm:"${certificate_dir}" + done + + # For cert9 (SQL) - Chromium and Chrome + for certificate_database in $(find "${browser_config_dir}" -name "cert9.db"); do + local certificate_dir=$(dirname ${certificate_database}) + certutil -A -n "${certificate_name}" -t "TCu,Cu,Tu" -i "${pem_certificate_file_path}" -d sql:"${certificate_dir}" + done + + exit 0 + fi + + printf "\n>>> CERTIFICATE FILE NOT FOUND FOR: ${pem_certificate_file_path}\n" +} + +Main "${@]" diff --git a/docker/build/resources/custom-ssl/trusted-store/nodejs/add-certificate-to-server.sh b/docker/build/resources/custom-ssl/trusted-store/nodejs/add-certificate-to-server.sh new file mode 100755 index 0000000..7d66c7f --- /dev/null +++ b/docker/build/resources/custom-ssl/trusted-store/nodejs/add-certificate-to-server.sh @@ -0,0 +1,49 @@ +#!/bin/sh + +set -eu + +Main() +{ + ############################################################################## + # INPUT + ############################################################################## + + local pem_certificate_file=${1? Missing certificate file name !!!} + local home_dir=${2? Missing home dir !!!} + + + ############################################################################## + # VARS + ############################################################################## + + local certificate_extension="${pem_certificate_file##*.}" + + + ############################################################################## + # EXECUTION + ############################################################################## + + if [ "${certificate_extension}" != "pem" ]; then + + printf "\nFATAL ERROR: Certificate must use .pem extension \n\n" + exit 1 + fi + + if [ -f "${pem_certificate_file}" ]; then + + printf "\n>>> ADDING A CERTIFICATE TO NODEJS SERVER <<<\n" + + # Add certificate to node, so that we can use npm install + printf "cafile=${pem_certificate_file}" >> /root/.npmrc + printf "cafile=${pem_certificate_file}" >> "${home_dir}"/.npmrc; + + printf "\n >>> CERTICATE ADDED SUCCESEFULY<<<\n" + + exit0 + fi + + printf "\n >>> NO CERTIFICATE TO ADD <<<\n" + +} + +Main "${@}" diff --git a/docker/build/resources/custom-ssl/trusted-store/operating-system/add-custom-authority-certificate.sh b/docker/build/resources/custom-ssl/trusted-store/operating-system/add-custom-authority-certificate.sh new file mode 100755 index 0000000..b4b66ef --- /dev/null +++ b/docker/build/resources/custom-ssl/trusted-store/operating-system/add-custom-authority-certificate.sh @@ -0,0 +1,35 @@ +#!/bin/sh + +set -eu + +Main() +{ + ############################################################################## + # INPUT + ############################################################################## + + local crt_certificate_file_path="${1? Missing path for CRT file of the custom authority certificate !!!}" + + + ############################################################################## + # EXECUTION + ############################################################################## + + if [ -f "${crt_certificate_file_path}" ]; then + + printf "\n>>> ADDING A CUSTOM AUTHORITY CERTIFICATE TO THE TRUSTED STORE <<<\n" + + # add certificate to the trust store + cp -v "${crt_certificate_file_path}" /usr/local/share/ca-certificates + update-ca-certificates + + # verifies the certificate + openssl x509 -in "${crt_certificate_file_path}" -text -noout > "${crt_certificate_file_path}.txt" + + exit 0 + fi + + printf "\n >>> No Custom Certificate to be added from path: ${crt_certificate_file_path} <<<\n" +} + +Main "${@}" diff --git a/docker/build/resources/custom-ssl/trusted-store/operating-system/config/localhost.txt b/docker/build/resources/custom-ssl/trusted-store/operating-system/config/localhost.txt new file mode 100644 index 0000000..9ffb34d --- /dev/null +++ b/docker/build/resources/custom-ssl/trusted-store/operating-system/config/localhost.txt @@ -0,0 +1,15 @@ +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +#extendedKeyUsage=serverAuth +subjectAltName = @alt_names + + +[ alt_names ] + +DNS.1 = localhost +DNS.2 = *.localhost diff --git a/docker/build/resources/custom-ssl/trusted-store/operating-system/config/openssl.cnf b/docker/build/resources/custom-ssl/trusted-store/operating-system/config/openssl.cnf new file mode 100644 index 0000000..a25e990 --- /dev/null +++ b/docker/build/resources/custom-ssl/trusted-store/operating-system/config/openssl.cnf @@ -0,0 +1,353 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca', 'req' and 'ts'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +# Policies used by the TSA examples. +tsa_policy1 = 1.2.3.4.1 +tsa_policy2 = 1.2.3.4.5.6 +tsa_policy3 = 1.2.3.4.5.7 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certs with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem# The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = default # use public key default MD +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 2048 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString (PKIX recommendation before 2004) +# utf8only: only UTF8Strings (PKIX recommendation after 2004). +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings. +string_mask = utf8only + +req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = AU +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Some-State + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = Internet Widgits Pty Ltd + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +#organizationalUnitName_default = + +commonName = Common Name (e.g. server FQDN or YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This is required for TSA certificates. +# extendedKeyUsage = critical,timeStamping + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +#extendedKeyUsage=serverAuth +#subjectAltName = @alt_names + + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer + +#basicConstraints = critical,CA:true +basicConstraints = critical, CA:TRUE, pathlen:3 + + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as an test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign +keyUsage = critical, cRLSign, keyCertSign + +# Some might want this also +nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo + +#################################################################### +[ tsa ] + +default_tsa = tsa_config1 # the default TSA section + +[ tsa_config1 ] + +# These are used by the TSA reply generation only. +dir = ./demoCA # TSA root directory +serial = $dir/tsaserial # The current serial number (mandatory) +crypto_device = builtin # OpenSSL engine to use for signing +signer_cert = $dir/tsacert.pem # The TSA signing certificate + # (optional) +certs = $dir/cacert.pem # Certificate chain to include in reply + # (optional) +signer_key = $dir/private/tsakey.pem # The TSA private key (optional) +signer_digest = sha256 # Signing digest to use. (Optional) +default_policy = tsa_policy1 # Policy if request did not specify it + # (optional) +other_policies = tsa_policy2, tsa_policy3 # acceptable policies (optional) +digests = sha1, sha256, sha384, sha512 # Acceptable message digests (mandatory) +accuracy = secs:1, millisecs:500, microsecs:100 # (optional) +clock_precision_digits = 0 # number of digits after dot. (optional) +ordering = yes # Is ordering defined for timestamps? + # (optional, default: no) +tsa_name = yes # Must the TSA name be included in the reply? + # (optional, default: no) +ess_cert_id_chain = no # Must the ESS cert id chain be included? + # (optional, default: no) diff --git a/docker/build/resources/custom-ssl/trusted-store/operating-system/create-and-add-self-signed-root-certificate.sh b/docker/build/resources/custom-ssl/trusted-store/operating-system/create-and-add-self-signed-root-certificate.sh new file mode 100755 index 0000000..8660715 --- /dev/null +++ b/docker/build/resources/custom-ssl/trusted-store/operating-system/create-and-add-self-signed-root-certificate.sh @@ -0,0 +1,73 @@ +#!/bin/sh + +set -eu + +################################################################################ +# +# Inspired by: +# * https://fabianlee.org/2018/02/17/ubuntu-creating-a-trusted-ca-and-san-certificate-using-openssl-on-ubuntu/ +# +# Creates and add a self signed root certificate to sign doamin to be used in a +# localhost development. +# +# To generate a domain for localhost development use: +# * ./custom-ssl/create-domain-certificate.sh +# + +Main() +{ + ############################################################################## + # IMPUT + ############################################################################## + + local root_certicate_name="${1:-Self_Signed_Root_CA}" + local openssl_config_file="${2:-./config/openssl.cnf}" + + + ############################################################################## + # VARS + ############################################################################## + + local root_certificate_key_file="${root_certicate_name}.key" + local root_certificate_pem_file="${root_certicate_name}.pem" + + + ############################################################################## + # EXECUTION + ############################################################################## + + if [ -f "${root_certificate_pem_file}" ]; then + + printf "\n >>> SELF SIGNED ROOT PEM CERTICATE FILE ALREADY EXISTS <<<\n" + + # we want only to return a warning, not an error. + exit 0 + fi + + printf "\n>>> CREATING A SELF SIGNED ROOT CERTIFICATE <<<\n" + + openssl req \ + -new \ + -newkey rsa:4096 \ + -days 3650 \ + -nodes \ + -x509 \ + -extensions v3_ca \ + -subj "/C=US/ST=CA/L=SF/O=${root_certicate_name}/CN=${root_certicate_name}" \ + -keyout "${root_certificate_key_file}" \ + -out "${root_certificate_pem_file}" \ + -config "${openssl_config_file}" + + printf "\n>>> ADDING SELF SIGNED ROOT CERTIFICATE TO THE OPERATING SYSTEM TRUSTED STORE <<<\n" + + # add certificate to the trust store + cp "${root_certificate_pem_file}" /usr/local/share/ca-certificates/"${root_certicate_name}".crt + update-ca-certificates + + # verifies the certificate + openssl x509 -in "${root_certificate_pem_file}" -text -noout > "${root_certicate_name}.txt" + + printf "\n >>> SELF SIGNED ROOT CERTICATE CREATED SUCCESEFULY<<<\n" +} + +Main "${@}" diff --git a/docker/build/resources/custom-ssl/trusted-store/operating-system/create-self-signed-domain-certificate.sh b/docker/build/resources/custom-ssl/trusted-store/operating-system/create-self-signed-domain-certificate.sh new file mode 100755 index 0000000..c3d422d --- /dev/null +++ b/docker/build/resources/custom-ssl/trusted-store/operating-system/create-self-signed-domain-certificate.sh @@ -0,0 +1,112 @@ +#!/bin/sh + +set -eu + + +################################################################################ +# +# Inspired by: +# * https://fabianlee.org/2018/02/17/ubuntu-creating-a-trusted-ca-and-san-certificate-using-openssl-on-ubuntu/ +# +# Creates and adds a self signed certificate for the given domain name to use in +# a localhost development. +# +# It will sign the certificate with the self signed root certificate from: +# * ./custom-ssl/trusted-store/operating-system/create-and-add-self-signed-root-certificate.sh +# + +Build_Domain_Config() +{ + local domain_name=${1? Missing domain name !!!} + + echo " +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +#extendedKeyUsage=serverAuth +subjectAltName = @alt_names + + +[ alt_names ] + +DNS.1 = ${domain_name} +DNS.2 = *.${domain_name} +" +} + +Main() +{ + ############################################################################## + # IMPUT + ############################################################################## + + local domain_name="${1:-localhost}" + local root_certicate_name="${2:-Self_Signed_Root_CA}" + local openssl_config_file="${3:-./config/openssl.cnf}" + + + ############################################################################## + # CONSTANT VARS + ############################################################################## + + local ROOT_CA_KEY="${root_certicate_name}.key" + local ROOT_CA_PEM="${root_certicate_name}.pem" + local DOMAIN_CA_KEY="${domain_name}.key" + local DOMAIN_CA_CSR="${domain_name}.csr" + local DOMAIN_CA_CRT="${domain_name}.crt" + local CONFIG_FILE="${domain_name}.cnf" + + + ############################################################################## + # EXECUTION + ############################################################################## + + printf "\n>>> CREATING DOMAIN CONFIGURATION INTO ${CONFIG_FILE} <<<\n" + local domain_config=$(Build_Domain_Config "${domain_name}") + local openssl_config=$(cat "${openssl_config_file}") + + echo "${openssl_config}" > "${CONFIG_FILE}" + echo "${domain_config}" >> "${CONFIG_FILE}" + + printf "\n>>> GENERATING KEY FOR DOMAIN CERTIFICATE: ${DOMAIN_CA_KEY} <<<\n" + + # generate the private/public RSA key pair for the domain + openssl genrsa -out "${DOMAIN_CA_KEY}" 4096 + + printf "\n>>> GENERATING CSR FOR DOMAIN CERTIFICATE: ${DOMAIN_CA_CSR} <<<\n" + + # create the server certificate signing request: + openssl req \ + -subj "/CN=${domain_name}" \ + -extensions v3_req \ + -sha256 \ + -new \ + -key "${DOMAIN_CA_KEY}" \ + -out "${DOMAIN_CA_CSR}" + + printf "\n>>> GENERATING CRT FOR DOMAIN CERTIFICATE: ${DOMAIN_CA_CRT} <<<\n" + + # generate the server certificate using the: server signing request, the CA signing key, and CA cert. + openssl x509 \ + -req \ + -extensions v3_req \ + -days 3650 \ + -sha256 \ + -in "${DOMAIN_CA_CSR}" \ + -CA "${ROOT_CA_PEM}" \ + -CAkey "${ROOT_CA_KEY}" \ + -CAcreateserial \ + -out "${DOMAIN_CA_CRT}" \ + -extfile "${CONFIG_FILE}" + + # verifies the certificate + openssl x509 -in "${DOMAIN_CA_CRT}" -text -noout > "${domain_name}".txt + + printf "\n >>> CERTIFICATE CREATED FOR DOMAIN: ${domain_name} <<<\n" +} + +Main "${@}" diff --git a/docker/build/resources/scripts/create-workspace-dir.sh b/docker/build/resources/scripts/create-workspace-dir.sh new file mode 100755 index 0000000..0f64856 --- /dev/null +++ b/docker/build/resources/scripts/create-workspace-dir.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +set -eu + +Main() +{ + ############################################################################## + # INPUT + ############################################################################## + + local workspace_path="${1? Missing path to work space dir !!!}" + local user_name=${2? Missing user name !!!} + + + ############################################################################## + # EXECUTION + ############################################################################## + + mkdir -p "${workspace_path}" + chown -R "${user_name}":"${user_name}" "${workspace_path}" +} + +Main "${@}" diff --git a/docker/build/resources/scripts/debian/install-firefox.sh b/docker/build/resources/scripts/debian/install-firefox.sh new file mode 100755 index 0000000..3257e81 --- /dev/null +++ b/docker/build/resources/scripts/debian/install-firefox.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +set -eu + +Main() +{ + ############################################################################## + # EXECUTION + ############################################################################## + + apt install -y -q --no-install-recommends \ + libcanberra-gtk3-module \ + firefox-esr +} + +Main "${@}" diff --git a/docker/build/resources/scripts/debian/install-inotify-tools.sh b/docker/build/resources/scripts/debian/install-inotify-tools.sh new file mode 100755 index 0000000..9398a2a --- /dev/null +++ b/docker/build/resources/scripts/debian/install-inotify-tools.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +set -eu + +Main() +{ + ############################################################################## + # EXECUTION + ############################################################################## + + apt install -y -q --no-install-recommends inotify-tools + + printf "fs.inotify.max_user_watches=524288\n" > /etc/sysctl.d/01-inotify.conf +} + +Main diff --git a/docker/build/resources/scripts/debian/install-locales.sh b/docker/build/resources/scripts/debian/install-locales.sh new file mode 100755 index 0000000..db544f6 --- /dev/null +++ b/docker/build/resources/scripts/debian/install-locales.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +set -eu + +Main() +{ + ############################################################################## + # INPUT + ############################################################################## + + local localization=${1? Missing localization for Locales !!!} + local encoding=${2? Missing encoding for Locales !!!} + + + ############################################################################## + # EXECUTION + ############################################################################## + + apt install -y -q --no-install-recommends locales + + echo "${localization} ${encoding}" > /etc/locale.gen + locale-gen "${encoding}" +} + +Main "${@}" diff --git a/docker/build/resources/scripts/debian/install-nodejs.sh b/docker/build/resources/scripts/debian/install-nodejs.sh new file mode 100755 index 0000000..bb85948 --- /dev/null +++ b/docker/build/resources/scripts/debian/install-nodejs.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +set -eu + +Main() +{ + ############################################################################## + # INPUT + ############################################################################## + + local node_version="${1? Missing node version!!!}" + + + ############################################################################## + # EXECUTION + ############################################################################## + + curl -sL https://deb.nodesource.com/setup_"${node_version}".x | sh - + + apt install -y -q --no-install-recommends nodejs +} + +Main "${@}" diff --git a/docker/build/resources/scripts/debian/install-pgcli.sh b/docker/build/resources/scripts/debian/install-pgcli.sh new file mode 100755 index 0000000..bab5a79 --- /dev/null +++ b/docker/build/resources/scripts/debian/install-pgcli.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +set -eu + +Main() +{ + ############################################################################## + # EXECUTION + ############################################################################## + + # python \ + # python-dev \ + # python-pip \ + apt install -y -q --no-install-recommends pgcli +} + +Main diff --git a/docker/build/resources/scripts/debian/install-postgres.sh b/docker/build/resources/scripts/debian/install-postgres.sh new file mode 100755 index 0000000..fd507df --- /dev/null +++ b/docker/build/resources/scripts/debian/install-postgres.sh @@ -0,0 +1,50 @@ +#!/bin/sh + +set -eu + +Main() +{ + ############################################################################## + # INPUT + ############################################################################## + + local debian_version_name=${1? Missing Debian version name} + local postgres_version=${2? Missing Postgres version !!!} + local user_name=${3? Missing container user name !!!} + + + ############################################################################## + # EXECUTION + ############################################################################## + + printf "\n>>> INSTALL POSTGRES VERSION: ${postgres_version} <<< \n" + + apt install -y -q --no-install-recommends \ + apt-transport-https \ + ca-certificates \ + gnupg2 + + printf "\n---> GNUPG2 IS INSTALLED \n" + + echo "deb http://apt.postgresql.org/pub/repos/apt/ ${debian_version_name}-pgdg main" > /etc/apt/sources.list.d/postgres.list + curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc -o pgp.key + apt-key add pgp.key + rm -f pgp.key + #apt-key adv --fetch-keys https://www.postgresql.org/media/keys/ACCC4CF8.asc + + apt update + apt install -y -q --no-install-recommends postgresql-"${postgres_version}" + + adduser "${user_name}" postgres + + ls -al /var/run/postgresql + #chmod -s /var/run/postgresql/"${postgres_version}"-main.pg_stat_tmp + chown -R "${user_name}":"${user_name}" /var/run/postgresql + ls -al /var/run/postgresql + + rm -rf /var/lib/postgresql/* + chown -R "${user_name}":"${user_name}" /var/lib/postgresql + ls -al /var/lib/postgresql +} + +Main "${@}" diff --git a/docker/build/resources/scripts/debian/install-sublime-text.sh b/docker/build/resources/scripts/debian/install-sublime-text.sh new file mode 100755 index 0000000..0ba1a68 --- /dev/null +++ b/docker/build/resources/scripts/debian/install-sublime-text.sh @@ -0,0 +1,106 @@ +#!/bin/sh + +set -eu + +Install_Package_Control() +{ + ############################################################################## + # INPUT + ############################################################################## + + local user_name=${1? Missing user name to install sublime for!!!} + + + ############################################################################## + # CONSTANT VARS + ############################################################################## + + local SUBLIME_CONFIG_DIR="/home/${user_name}/.config/sublime-text-3" + + + ############################################################################## + # EXECUTION + ############################################################################## + + printf "\n---> INSTALL PACKAGE CONTROL FOR SUBLIME TEXT 3 \n" + + # Create default dirs in User home directory necessary for Sublime + su "${user_name}" -c "sh -c 'mkdir -p /home/${user_name}/.local/share'" + su "${user_name}" -c "sh -c 'mkdir -p ${SUBLIME_CONFIG_DIR}/Cache'" + su "${user_name}" -c "sh -c 'mkdir -p ${SUBLIME_CONFIG_DIR}/Local'" + su "${user_name}" -c "sh -c 'mkdir -p ${SUBLIME_CONFIG_DIR}/Index'" + su "${user_name}" -c "sh -c 'mkdir -p ${SUBLIME_CONFIG_DIR}/Installed\ Packages'" + su "${user_name}" -c "sh -c 'mkdir -p ${SUBLIME_CONFIG_DIR}/Packages/User'" + + su "${user_name}" -c "sh -c 'curl -fsSL https://packagecontrol.io/Package%20Control.sublime-package -o ${SUBLIME_CONFIG_DIR}/Installed\ Packages/Package\ Control.sublime-package'" +} + +Main() +{ + ############################################################################## + # INPUT + ############################################################################## + + local sublime_build=${1:-latest} + local user_name=${2? Missing user name!!!} + local docker_build_resources_dir="${3? Missing path to docker build resources dir!!!}" + + + ################################################################################ + # VAR CONSTANTS + ################################################################################ + + local SUBLIME_PACKAGES_DIR=/home/"${user_name}"/.config/sublime-text-3/Packages + local SCRIPT_DIR="${docker_build_resources_dir}"/scripts/sublime-text-3/"${user_name}" + + + ############################################################################## + # EXECUTION + ############################################################################## + + printf "\n>>>>>>>>>> INSTALLING SUBLIME TEXT 3 FOR USER: ${user_name} <<<<<<<<<<\n" + + if [ -z "${sublime_build}" ]; then + printf "\n---> SUBLIME BUILD IS INVALID \n" + exit 1 + fi + + apt install -y --no-install-recommends \ + dbus-x11 \ + libcanberra-gtk3-module + + if [ "${sublime_build}" = "latest" ]; then + + printf "\n---> APT will be used to install Sublime for build: ${sublime_build} \n" + + apt install -y -q --no-install-recommends \ + apt-transport-https \ + ca-certificates + + curl -fsSL https://download.sublimetext.com/sublimehq-pub.gpg -o pgp.key + apt-key add pgp.key + rm -f pgp.key + #apt-key adv --fetch-keys https://download.sublimetext.com/sublimehq-pub.gpg + + echo "deb https://download.sublimetext.com/ apt/stable/" > /etc/apt/sources.list.d/sublime-text.list + + apt update + + apt install -y --no-install-recommends sublime-text + + else + + printf "\n---> DPKG will be used to install Sublime for build: ${sublime_build} \n" + + curl -O https://download.sublimetext.com/sublime-text_build-"${sublime_build}"_amd64.deb + + dpkg -i sublime-text_build-"${sublime_build}"_amd64.deb + + fi + + Install_Package_Control "${user_name}" + + cp -r "${SCRIPT_DIR}"/.config/sublime-text-3/Packages/User "${SUBLIME_PACKAGES_DIR}" +} + +Main "${@}" diff --git a/docker/build/resources/scripts/debian/install-visual-studio-code.sh b/docker/build/resources/scripts/debian/install-visual-studio-code.sh new file mode 100755 index 0000000..410df3e --- /dev/null +++ b/docker/build/resources/scripts/debian/install-visual-studio-code.sh @@ -0,0 +1,37 @@ +#!/bin/sh + +set -eu + +Main() +{ + ############################################################################## + # CONSTANT VARS + ############################################################################## + + local VSCODE_FILE="vsc.deb" + + + ############################################################################## + # EXECUTION + ############################################################################## + + # Install Visual Studio Code + curl -L 'https://go.microsoft.com/fwlink/?LinkID=760868' -o "${VSCODE_FILE}" + + apt install -y --no-install-recommends ./"${VSCODE_FILE}" \ + apt-transport-https \ + libasound2 \ + libcanberra-gtk-module \ + libgconf-2-4 \ + libasound2 \ + libgtk2.0-0 \ + libxss1 + + apt update + apt install -y code + + # Force installation of missing dependencies for Visual Studio Code + apt -y -f install +} + +Main diff --git a/docker/build/resources/scripts/debian/remove-build-deps.sh b/docker/build/resources/scripts/debian/remove-build-deps.sh new file mode 100755 index 0000000..194738a --- /dev/null +++ b/docker/build/resources/scripts/debian/remove-build-deps.sh @@ -0,0 +1,53 @@ +#!/bin/sh + +set -eu + +Main() +{ + ################################################################################ + # EXECUTION + ################################################################################ + + apt purge -y --auto-remove \ + autoconf \ + automake \ + bzip2 \ + dpkg-dev \ + file \ + g++ \ + gcc \ + imagemagick \ + libbz2-dev \ + libc6-dev \ + libcurl4-openssl-dev \ + libdb-dev \ + libevent-dev \ + libffi-dev \ + libgdbm-dev \ + libgeoip-dev \ + libglib2.0-dev \ + libgmp-dev \ + libjpeg-dev \ + libkrb5-dev \ + liblzma-dev \ + libmagickcore-dev \ + libmagickwand-dev \ + libncurses5-dev \ + libncursesw5-dev \ + libpng-dev \ + libpq-dev \ + libreadline-dev \ + libsqlite3-dev \ + libssl-dev \ + libtool \ + libwebp-dev \ + libxml2-dev \ + libxslt-dev \ + libyaml-dev \ + make \ + patch \ + xz-utils \ + zlib1g-dev +} + +Main diff --git a/docker/build/resources/scripts/elixir/bin/elixir-server b/docker/build/resources/scripts/elixir/bin/elixir-server new file mode 100755 index 0000000..cc667db --- /dev/null +++ b/docker/build/resources/scripts/elixir/bin/elixir-server @@ -0,0 +1,31 @@ +#!/bin/sh + +set -eu + +Main() +{ + ############################################################################## + # INPUT + ############################################################################## + + local app_name="${1? Missing app name!!!}" + local node_cookie="${2? Missing node cookie!!!}" + local phoenix_command=${3:-phx.server} + + local node_name="${app_name}@$(hostname -i)" + + ############################################################################## + # EXECUTION + ############################################################################## + + printf "\n---> NODE NAME: ${node_name}\n" + printf "\n---> NODE COOKIE: ${node_cookie}\n" + + elixir \ + --cookie "${node_cookie}" \ + --name "${node_name}" \ + -S mix "${phoenix_command}" + +} + +Main "${@}" diff --git a/docker/build/resources/scripts/elixir/bin/observer b/docker/build/resources/scripts/elixir/bin/observer new file mode 100755 index 0000000..7c09374 --- /dev/null +++ b/docker/build/resources/scripts/elixir/bin/observer @@ -0,0 +1,64 @@ +#!/bin/sh + +set -eu + +Main() +{ + ############################################################################## + # INPUT + ############################################################################## + + if [ "$#" -ge 1 ]; then + + # eg: acme-app + local node_name="${1? Missing node name!!!}" + + # eg: 172.24.0.2 + local node_address="${2? Missing node address!!!}" + + # eg: -7sXSFr5CfAlj|".0>`ci84E$0c9LEQtZ-pP0d:[qY.)#U|5Fp[3{_7U%R`- + local node_cookie="${3? Missing node cookie!!!}" + + # eg: acme-app@172.24.0.2 + local app_node_name="${node_name}@${node_address}" + + else + + # GET FROM ENVIRONMENT WHEN NO ARGUMENTS ARE PASSED TO THE SCRIPT + + # eg: acme-app@172.24.0.2 + local app_node_name="${APP_NODE_NAME}" + + # eg: -7sXSFr5CfAlj|".0>`ci84E$0c9LEQtZ-pP0d:[qY.)#U|5Fp[3{_7U%R`- + local node_cookie="${APP_NODE_COOKIE}" + fi + + # observer@172.24.0.3 + local observer_node_name="observer@$(hostname -i)" + + + ############################################################################## + # EXECUTION + ############################################################################## + + # @link https://elixirforum.com/t/is-possible-to-use-observer-with-multiple-applications/21617 + local app_node_name="$(echo ${app_node_name} | tr -d '\n\r\t ')" + + # Node.connect(:"acme-app@172.24.0.2") + local node_connect="Node.connect(:\"${app_node_name}\")" + + printf "\n---> iex --name '${observer_node_name}' --cookie '${node_cookie}' -e '${node_connect}' -e ':observer.start()'\n\n" + + # iex \ + # --name 'observer@172.24.0.3' \ + # --cookie '-7sXSFr5CfAlj|".0>`ci84E$0c9LEQtZ-pP0d:[qY.)#U|5Fp[3{_7U%R`-' \ + # -e 'Node.connect(:"acme-app@172.24.0.2")' \ + # -e ':observer.start()' + iex \ + --name "${observer_node_name}" \ + --cookie "${node_cookie}" \ + -e "${node_connect}" \ + -e ":observer.start()" +} + +Main "${@}" diff --git a/docker/build/resources/scripts/elixir/bin/observer-cli b/docker/build/resources/scripts/elixir/bin/observer-cli new file mode 100755 index 0000000..3852926 --- /dev/null +++ b/docker/build/resources/scripts/elixir/bin/observer-cli @@ -0,0 +1,63 @@ +#!/bin/sh + +set -eu + +Main() +{ + ############################################################################## + # INPUT + ############################################################################## + + if [ "$#" -ge 1 ]; then + + # eg: acme-app + local node_name="${1? Missing node name!!!}" + + # eg: 172.24.0.2 + local node_address="${2? Missing node address!!!}" + + # eg: -7sXSFr5CfAlj|".0>`ci84E$0c9LEQtZ-pP0d:[qY.)#U|5Fp[3{_7U%R`- + local node_cookie="${3? Missing node cookie!!!}" + + # eg: acme-app@172.24.0.2 + local app_node_name="${node_name}@${node_address}" + + else + + # GET FROM ENVIRONMENT WHEN NO ARGUMENTS ARE PASSED TO THE SCRIPT + + # eg: acme-app@172.24.0.2 + local app_node_name="${APP_NODE_NAME}" + + # eg: -7sXSFr5CfAlj|".0>`ci84E$0c9LEQtZ-pP0d:[qY.)#U|5Fp[3{_7U%R`- + local node_cookie="${APP_NODE_COOKIE}" + fi + + # observer@172.24.0.3 + local observer_node_name="observer@$(hostname -i)" + + + ############################################################################## + # EXECUTION + ############################################################################## + + # @link https://elixirforum.com/t/is-possible-to-use-observer-with-multiple-applications/21617 + local app_node_name="$(echo ${app_node_name} | tr -d '\n\r\t ')" + + cat <<-HEREDOC + + ############################################################## + # # + # iex(${app_node_name})> :observer_cli.start() # + # # + ############################################################## + +HEREDOC + + iex \ + --name "${observer_node_name}" \ + --cookie "${node_cookie}" \ + --remsh "${app_node_name}" +} + +Main "${@}" diff --git a/docker/build/resources/scripts/elixir/observer/fix-dependencies.sh b/docker/build/resources/scripts/elixir/observer/fix-dependencies.sh new file mode 100755 index 0000000..b74e6e4 --- /dev/null +++ b/docker/build/resources/scripts/elixir/observer/fix-dependencies.sh @@ -0,0 +1,96 @@ +#!/bin/sh + +set -eu + +Main() +{ + ############################################################################## + # VARS + ############################################################################## + + local erlang_lib_dir=/usr/local/lib/erlang/lib + + local erlang_wx=$( find ${erlang_lib_dir} -name 'wx-*' ) + + local erlang_wx_version=${erlang_wx##*/} + + local erlang_wx_dir=/usr/lib/erlang/lib/"${erlang_wx_version}" + + + ############################################################################## + # EXECUTION + ############################################################################## + + printf "\n>>> FIXING OBSERVER DEPENDENCIES FOR ERLANG WX VERSION: ${erlang_wx_version} <<< \n" + + # apt install -y --no-install-recommends \ + # libcanberra-gtk-module \ + # libcanberra-gtk3-module \ + # libwxgtk3.0 + + # runtimeDeps=' + # libodbc1 + # libssl1.1 + # libsctp1 + # libwxgtk3.0 + # ' + # buildDeps=' + # autoconf + # dpkg-dev + # gcc + # g++ + # make + # libncurses-dev + # unixodbc-dev + # libssl-dev + # libsctp-dev + # libwxgtk3.0-dev + # ' + + # apt install -y --no-install-recommends ${runtimeDeps} + # apt install -y --no-install-recommends ${buildDeps} + + # https://github.com/asdf-vm/asdf-erlang#before-asdf-install + # apt-get -y install \ + # libwxgtk3.0-dev \ + # libgl1-mesa-dev \ + # libglu1-mesa-dev \ + # libpng-dev + + apt install -y -q --no-install-recommends \ + libsctp-dev \ + libwxbase3.0-dev\ + libwxgtk3.0-dev \ + libcanberra-gtk-module + + apt install -y -q --no-install-recommends \ + erlang-x11 \ + erlang-wx + + #apt purge -y --auto-remove $buildDeps + + printf "\n---> Trying to fix Observer using dir: ${erlang_wx_dir}\n" + + if [ -d "${erlang_wx_dir}" ]; then + # https://elixirforum.com/t/observer-start-is-not-working-on-ubuntu/6018/21?u=exadra37 + #rm -rf "${erlang_lib_dir}/${erlang_wx_version}" + mv "${erlang_lib_dir}/${erlang_wx_version}" / + ln -s "${erlang_wx_dir}" "${erlang_lib_dir}" + printf "\n---> Fixed Observer by linking ${erlang_lib_dir}/${erlang_wx_version} to ${erlang_wx_dir}\n" + exit 0 + fi + + erlang_wx_dir_2="${erlang_wx_dir%.*}" + + printf "\n---> Trying to fix Observer using dir: ${erlang_wx_dir_2}\n" + + if [ -d "${erlang_wx_dir_2}" ]; then + # https://elixirforum.com/t/observer-start-is-not-working-on-ubuntu/6018/21?u=exadra37 + #rm -rf "${erlang_lib_dir}/${erlang_wx_version}" + mv "${erlang_lib_dir}/${erlang_wx_version}" / + ln -s "${erlang_wx_dir_2}" "${erlang_lib_dir}/${erlang_wx_version}" + printf "\n---> Fixed Observer by linking ${erlang_lib_dir}/${erlang_wx_version} to ${erlang_wx_dir_2}\n" + fi +} + +Main diff --git a/docker/build/resources/scripts/elixir/phoenix/install.sh b/docker/build/resources/scripts/elixir/phoenix/install.sh new file mode 100755 index 0000000..3c2dc8e --- /dev/null +++ b/docker/build/resources/scripts/elixir/phoenix/install.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +set -eu + +Main() +{ + ################################################################################ + # INPUT + ################################################################################ + + local phoenix_version="${1? Missing Phoenix version to install!!!}" + + local phoenix_install_from="hex phx_new ${phoenix_version}" + + # from 1.4.0 assigns 1.4 + local phoenix_major_version="${phoenix_version%.*}" + + # Phoenix framework installation procedure changed from 1.4 onwards. + if [ "${phoenix_major_version}" \< "1.4" ]; then + phoenix_install_from="https://github.com/phoenixframework/archives/raw/master/phx_new-${phoenix_version}.ez" + fi + + ################################################################################ + # EXECUTION + ################################################################################ + + # installs the package manager + mix local.hex --force + + # installs rebar and rebar3 + mix local.rebar --force + + ln -s "${HOME}"/.mix/rebar "${HOME}"/bin/rebar + ln -s "${HOME}"/.mix/rebar3 "${HOME}"/bin/rebar3 + + mix archive.install --force ${phoenix_install_from} +} + +Main "${@}" diff --git a/docker/build/resources/scripts/install-oh-my-zsh.sh b/docker/build/resources/scripts/install-oh-my-zsh.sh new file mode 100755 index 0000000..80c5e4a --- /dev/null +++ b/docker/build/resources/scripts/install-oh-my-zsh.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +set -eu + +Main() +{ + ############################################################################## + # INPUT + ############################################################################## + + local home_dir=${1? Missing the home dir !!!} + local oh_my_zsh_theme=${2:-robbyrussell} + + + ############################################################################## + # EXECUTION + ############################################################################## + + apt install -y --no-install-recommends zsh + + sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)" + + cp -v /root/.zshrc "${home_dir}"/.zshrc + + cp -r /root/.oh-my-zsh "${home_dir}"/.oh-my-zsh + + sed -i "s|/root|${home_dir}|g" "${home_dir}"/.zshrc + + sed -i "s/ZSH_THEME=\"robbyrussell\"/ZSH_THEME=\"${oh_my_zsh_theme}\"/g" "${home_dir}"/.zshrc +} + +Main "${@}" diff --git a/docker/build/resources/scripts/setup-postgres.sh b/docker/build/resources/scripts/setup-postgres.sh new file mode 100755 index 0000000..fdbec3c --- /dev/null +++ b/docker/build/resources/scripts/setup-postgres.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +set -eu + +Main() +{ + ############################################################################## + # INPUT + ############################################################################## + + local postgres_version=${1? Missing Postgres version !!!} + local postgres_user=${2? Missing Postgres user !!!} + local postgres_password=${3? Missing postgres_password !!!} + + + ############################################################################## + # EXECUTION + ############################################################################## + + # initdb + bash -c "eval 'initdb --allow-group-access --username=postgres --pwfile=<(echo postgres)'" + + # https://docs.docker.com/engine/examples/postgresql_service/ + pg_ctl start + #psql -c "CREATE USER postgres WITH SUPERUSER PASSWORD 'postgres'" + createdb --username postgres --owner postgres testapp_dev + createdb --username postgres --owner postgres testapp_test + createdb --username postgres --owner postgres testapp_prod +} + +Main "${@}" diff --git a/docker/build/resources/scripts/show-hostname-ip-address.sh b/docker/build/resources/scripts/show-hostname-ip-address.sh new file mode 100755 index 0000000..11b6f19 --- /dev/null +++ b/docker/build/resources/scripts/show-hostname-ip-address.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +set -eu + +Main() +{ + ############################################################################## + # EXECUTION + ############################################################################## + + local hostname_with_ip_address="$(hostname -s)@$(hostname -i)" + + if [ "${1}" = "--quiet" ]; then + echo ${hostname_with_ip_address} + else + printf "\n\n>>> OBSERVER REMOTE SHELL ADDRESS: ${hostname_with_ip_address}" + fi + +} + +Main "${@}" diff --git a/docker/build/resources/scripts/sublime-text-3/elixir/.config/sublime-text-3/Packages/User/Package Control.sublime-settings b/docker/build/resources/scripts/sublime-text-3/elixir/.config/sublime-text-3/Packages/User/Package Control.sublime-settings new file mode 100644 index 0000000..41ce24e --- /dev/null +++ b/docker/build/resources/scripts/sublime-text-3/elixir/.config/sublime-text-3/Packages/User/Package Control.sublime-settings @@ -0,0 +1,13 @@ +{ + "bootstrapped": true, + "in_process_packages": + [ + ], + "installed_packages": + [ + "Dockerfile Syntax Highlighting", + "Elixir", + "ElixirSyntax", + "Package Control" + ] +} diff --git a/docker/build/resources/scripts/sublime-text-3/elixir/.config/sublime-text-3/Packages/User/Preferences.sublime-settings b/docker/build/resources/scripts/sublime-text-3/elixir/.config/sublime-text-3/Packages/User/Preferences.sublime-settings new file mode 100644 index 0000000..e8ab8ae --- /dev/null +++ b/docker/build/resources/scripts/sublime-text-3/elixir/.config/sublime-text-3/Packages/User/Preferences.sublime-settings @@ -0,0 +1,18 @@ +{ + "bold_folder_labels": true, + "ensure_newline_at_eof_on_save": true, + "highlight_modified_tabs": true, + "ignored_packages": + [ + "Vintage" + ], + "rulers": + [ + 80 + ], + "show_encoding": true, + "spell_check": true, + "translate_tabs_to_spaces": true, + "theme": "Adaptive.sublime-theme", + "trim_trailing_white_space_on_save": true +} diff --git a/docker/build/resources/scripts/sublime-text-3/elixir/language-server-protocol/.config/sublime-text-3/Packages/User/LSP.sublime-settings b/docker/build/resources/scripts/sublime-text-3/elixir/language-server-protocol/.config/sublime-text-3/Packages/User/LSP.sublime-settings new file mode 100644 index 0000000..98f087c --- /dev/null +++ b/docker/build/resources/scripts/sublime-text-3/elixir/language-server-protocol/.config/sublime-text-3/Packages/User/LSP.sublime-settings @@ -0,0 +1,32 @@ +{ + "auto_show_diagnostics_panel_level": 4, + "clients": + { + "elixir-ls": + { + "command": + [ + "elixir-ls" + ], + "enabled": true, + "languageId": "elixir", + "scopes": + [ + "source.elixir" + ], + "syntaxes": + [ + "Packages/ElixirSyntax/Elixir.sublime-syntax" + ] + } + }, + "diagnostics_highlight_style": "box", + "log_debug": true, + "log_payloads": true, + "log_stderr": true, + "only_show_lsp_completions": true, + "resolve_completion_for_snippets": true, + "show_code_actions_bulb": true, + "show_diagnostics_phantoms": true, + "show_diagnostics_severity_level": 4 +} diff --git a/docker/build/resources/scripts/sublime-text-3/elixir/language-server-protocol/bin/elixir-ls b/docker/build/resources/scripts/sublime-text-3/elixir/language-server-protocol/bin/elixir-ls new file mode 100755 index 0000000..22e14dd --- /dev/null +++ b/docker/build/resources/scripts/sublime-text-3/elixir/language-server-protocol/bin/elixir-ls @@ -0,0 +1,14 @@ +#!/bin/sh + +set -eu + +Main() +{ + ############################################################################## + # EXECUTION + ############################################################################## + + /home/elixir/elixir-ls/rel/language_server.sh +} + +Main diff --git a/docker/build/resources/scripts/sublime-text-3/elixir/language-server-protocol/install.sh b/docker/build/resources/scripts/sublime-text-3/elixir/language-server-protocol/install.sh new file mode 100755 index 0000000..c957fa2 --- /dev/null +++ b/docker/build/resources/scripts/sublime-text-3/elixir/language-server-protocol/install.sh @@ -0,0 +1,56 @@ +#!/bin/sh + +set -eu + +Main() +{ + ################################################################################ + # IMPUT + ################################################################################ + + local home_dir="${1? Missing path to container home dir !!!}" + local elixir_version="${2? Missing Elixir version!!!}" + local docker_build_resources_dir="${3? Missing path to docker build resources dir !!!}" + + + ################################################################################ + # VAR CONSTANTS + ################################################################################ + + local SUBLIME_PACKAGES_DIR="${home_dir}"/.config/sublime-text-3/Packages + local SETUP_DIR="${docker_build_resources_dir}"/scripts/sublime-text-3/elixir/language-server-protocol + + + ################################################################################ + # EXECUTION + ################################################################################ + + printf "\n>>> INSTALL ELIXIR LANGUAGE SERVER <<<\n" + + # from 1.7.0 assigns 1.7 + version="${elixir_version%.*}" + + if [ "${version}" \< "1.7" ]; then + printf "\n---> WARNING: The Elixir Language Server requires a Elixir 1.7 or greater, and current version is ${elixir_version}. Skipping installation. \n" + exit 0 + fi + + git clone https://github.com/tomv564/LSP.git "${SUBLIME_PACKAGES_DIR}"/LSP + + git clone https://github.com/JakeBecker/elixir-ls.git "${home_dir}"/elixir-ls + #git clone https://github.com/elixir-lsp/elixir-ls.git "${home_dir}"/elixir-ls + + cd "${home_dir}"/elixir-ls + mix deps.get + MIX_ENV=prod mix elixir_ls.release -o rel + + mkdir -p "${home_dir}"/bin + + cp -v "${SETUP_DIR}"/bin/elixir-ls "${home_dir}"/bin/elixir-ls + + mkdir -p "${SUBLIME_PACKAGES_DIR}"/User + + cp -r "${SETUP_DIR}"/.config/sublime-text-3/Packages/User/LSP.sublime-settings "${SUBLIME_PACKAGES_DIR}"/User/LSP.sublime-settings +} + +Main "${@}" diff --git a/docker/build/resources/scripts/sublime-text-3/setup.sh b/docker/build/resources/scripts/sublime-text-3/setup.sh new file mode 100755 index 0000000..8eb35c5 --- /dev/null +++ b/docker/build/resources/scripts/sublime-text-3/setup.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +set -eu + + +Main() +{ + ################################################################################ + # INPUT + ################################################################################ + + local home_dir="${1? Missing home dir !!!}" + local docker_build_resources_dir="${2? Missing path to docker build resources dir !!!}" + + + ################################################################################ + # VAR CONSTANTS + ################################################################################ + + local SUBLIME_PACKAGES_DIR="${home_dir}"/.config/sublime-text-3/Packages + local SCRIPT_DIR="${docker_build_resources_dir}"/scripts/sublime-text-3 + + + ################################################################################ + # EXECUTION + ################################################################################ + + + mkdir -p "${SUBLIME_PACKAGES_DIR}"/User + + cp -r "${SCRIPT_DIR}"/.config/sublime-text-3/Packages/User "${SUBLIME_PACKAGES_DIR}" +} + +Main "${@}" diff --git a/docs/demos/elixir-hello-world.md b/docs/demos/elixir-hello-world.md deleted file mode 100644 index fa85ee8..0000000 --- a/docs/demos/elixir-hello-world.md +++ /dev/null @@ -1,7 +0,0 @@ -# ELIXIR - HELLO WORLD DEMO - - - ---- - -[HOME](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/README.md) diff --git a/docs/how-to/create_a_merge_request.md b/docs/how-to/create_a_merge_request.md deleted file mode 100644 index d978f6b..0000000 --- a/docs/how-to/create_a_merge_request.md +++ /dev/null @@ -1,14 +0,0 @@ -# CREATE A MERGE REQUEST - -When opening your Merge Request ensure to do it against the `master` branch. - -Merge requests must use one of the available templates and all topics marked as `required` must be filled. - -All optional topics not used must maintain their title and have their body replaced by 'N/A'. - - ---- - -[<< previous](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/docs/how-to/create_branches.md) | [next >>](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/AUTHOR.md) - -[HOME](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/README.md) diff --git a/docs/how-to/create_an_issue.md b/docs/how-to/create_an_issue.md deleted file mode 100644 index a30317d..0000000 --- a/docs/how-to/create_an_issue.md +++ /dev/null @@ -1,45 +0,0 @@ -# CREATE AN ISSUE - -Always perform a search to see if your Issue as been already reported. - - -## Generic Guidelines - -Issues must use one of the available templates and all topics marked as required must be filled, by erasing the current -help and example info on them and write your own text. - -All optional topics not used must maintain their title and have their body replaced by 'N/A'. - -When any created issue do not follow this guidelines it will not be considered. - -Each issue will have is own Branch that are created as demonstrated [here](create_branches.md). - - -## Bug Fix / Security Fix - -Each issue should only target a specific bug or security flaw, unless they are tightly coupled to the point you can't -solve them separately. - -Create the issue [here](https://gitlab.com/exadra37-docker/elixir/elixir/issues/new) with the template -`bug_or_security_fix.md`. - - -## New Feature / Improve Feature / Refracting Code - -Starts with the [Creation of a Milestone](https://gitlab.com/exadra37-docker/elixir/elixir/milestones/new). - -Now we should split what we want to do in many tasks as we can by creating an Issue for each task and assign the issue -to the Milestone. - -Create each issue [here](https://gitlab.com/exadra37-docker/elixir/elixir/issues/new) using the relevant template: - -* `new_feature.md` -* `improve_feature.md` -* `refracting_code.md` - - ---- - -[<< previous](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/CONTRIBUTING.md) | [next >>](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/docs/how-to/create_branches.md) - -[HOME](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/README.md) diff --git a/docs/how-to/create_branches.md b/docs/how-to/create_branches.md deleted file mode 100644 index cdd7334..0000000 --- a/docs/how-to/create_branches.md +++ /dev/null @@ -1,54 +0,0 @@ -# CREATE BRANCHES - -Depending on the type of issue the branch for it will have a different origin. - - -## BUG FIX / SECURITY FIX - -As per [Issues Guidelines](docs/how-to/create_an_issue.md) we do not need to have a Milestone for it. - -Considering that we have issue number `4` with title `Fix Email Validation`. - -```bash -git fetch && git checkout -b issue-4_fix-email-validation origin/master -``` - - -## NEW FEATURE / IMPROVE FEATURE / REFRACTING CODE - -As per [Issues Guidelines](docs/how-to/create_an_issue.md) we must have a Milestone for this type of requirement. - -Once the Milestone can be split in several issues, lets imagine: - -* Milestone number `12` with title `Add Cache`. -* Issue number `14` with title `Create Cache Interfaces`. -* Issue number `15` with title `Implement Redis Cache`. -* Issue number `16` with title `Implement File System Cache`. - - -#### Creating Milestone Branch: - -```bash -git fetch && git checkout -b milestone-12_add-cache origin/master && git push origin milestone-12_add-cache -``` - -#### Creating Issues Branches: - -```bash -git fetch && git checkout -b issue-14_create-cache-interfaces origin/milestone-12_add-cache -``` - -```bash -git fetch && git checkout -b issue-15_implement-redis-cache` origin/milestone-12_add-cache -``` - -```bash -git fetch && git checkout -b issue-16_implement-file-system-cache` origin/milestone-12_add-cache -``` - - ---- - -[<< previous](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/docs/how-to/create_an_issue.md) | [next >>](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/docs/how-to/create_a_merge_request.md) - -[HOME](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/README.md) diff --git a/docs/how-to/install.md b/docs/how-to/install.md deleted file mode 100644 index b593f36..0000000 --- a/docs/how-to/install.md +++ /dev/null @@ -1,9 +0,0 @@ -# HOW TO INSTALL - - - ---- - -[<< previous](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/docs/the-package/why_exists.md) | [next >>](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/docs/how-to/use.md) - -[HOME](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/README.md) diff --git a/docs/how-to/uninstall.md b/docs/how-to/uninstall.md deleted file mode 100644 index 10c5633..0000000 --- a/docs/how-to/uninstall.md +++ /dev/null @@ -1,9 +0,0 @@ -# HOW TO UNINSTALL - - - ---- - -[<< previous](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/docs/how-to/create_a_merge_request.md) | [next >>](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/AUTHOR.md) - -[HOME](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/README.md) diff --git a/docs/how-to/use.md b/docs/how-to/use.md deleted file mode 100644 index c2c310f..0000000 --- a/docs/how-to/use.md +++ /dev/null @@ -1,9 +0,0 @@ -# HOW TO USE - - - ---- - -[<< previous](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/docs/how-to/install.md) | [next >>](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/CONTRIBUTING.md) - -[HOME](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/README.md) diff --git a/docs/the-package/what_is_it.md b/docs/the-package/what_is_it.md deleted file mode 100644 index fe91f52..0000000 --- a/docs/the-package/what_is_it.md +++ /dev/null @@ -1,10 +0,0 @@ -# WHAT IS IT? - - - ---- - -[<< previous](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/docs/the-package/why_exists.md) | [next >>](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/docs/the-package/when_to_use_it.md) - -[HOME](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/README.md) - diff --git a/docs/the-package/when_to_use_it.md b/docs/the-package/when_to_use_it.md deleted file mode 100644 index 1095ed2..0000000 --- a/docs/the-package/when_to_use_it.md +++ /dev/null @@ -1,9 +0,0 @@ -# WHEN TO USE IT? - - - ---- - -[<< previous](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/docs/the-package/what_is_it.md) | [next >>](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/docs/how-to/install.md) - -[HOME](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/README.md) diff --git a/docs/the-package/why_exists.md b/docs/the-package/why_exists.md deleted file mode 100644 index f2c0c9b..0000000 --- a/docs/the-package/why_exists.md +++ /dev/null @@ -1,10 +0,0 @@ -# WHY EXISTS? - - - ---- - -[<< previous](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/README.md) | [next >>](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/docs/the-package/what_is_it.md) - -[HOME](https://gitlab.com/exadra37-docker/elixir/elixir/blob/master/README.md) - diff --git a/src/bin/elixir b/src/bin/elixir deleted file mode 100755 index a080d15..0000000 --- a/src/bin/elixir +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash - -TAG=1.4 -ENTRYPOINT=elixir - -for argument in "${@}" - do - case "${argument}" in - --tag | -t) - TAG="${1}" - shift 1 - ;; - bash) - ENTRYPOINT=bash - shift 1 - ;; - iex) - ENTRYPOINT=iex - shift 1 - ;; - mix) - ENTRYPOINT=mix - shift 1 - ;; - esac -done - -sudo docker \ - run \ - --rm \ - -it \ - --volume "${PWD}":/home/elixir/workspace \ - exadra37/elixir:"${TAG}" \ - "${ENTRYPOINT}" "${@}" diff --git a/src/build/1.4/Dockerfile b/src/build/1.4/Dockerfile deleted file mode 100644 index b4eb68c..0000000 --- a/src/build/1.4/Dockerfile +++ /dev/null @@ -1,39 +0,0 @@ -FROM elixir:1.4 - -ARG CONTAINER_USER="elixir" -ARG LANGUAGE_CODE="en" -ARG COUNTRY_CODE="GB" -ARG ENCODING="UTF-8" - -ARG LOCALE_STRING="${LANGUAGE_CODE}_${COUNTRY_CODE}" -ARG LOCALIZATION="${LOCALE_STRING}.${ENCODING}" - -ENV DEBIAN_FRONTEND=noninteractive - -RUN apt-get update && \ - apt-get -y upgrade && \ - apt-get -y install \ - locales \ - inotify-tools && \ - apt-get -y -f install && \ - - # Locales - echo "${LOCALIZATION} ${ENCODING}" > /etc/locale.gen && \ - locale-gen "${LOCALIZATION}" && \ - - useradd -m -u 1000 -s /usr/bin/bash "${CONTAINER_USER}" - -USER "${CONTAINER_USER}" - -ENV LANG "${LOCALIZATION}" -ENV LANGUAGE "${LOCALE_STRING}:${LANGUAGE_CODE}" -ENV LC_ALL "${LOCALIZATION}" - -# Set the work dir for the container user defined above -WORKDIR /home/elixir/workspace - -# This commands will run under user defined above -RUN mix local.hex --force && \ - mix local.rebar --force - -CMD ["elixir"]