diff --git a/ecs/Dockerfile b/ecs/Dockerfile index 8068d7f..d75a4a4 100644 --- a/ecs/Dockerfile +++ b/ecs/Dockerfile @@ -1,3 +1,32 @@ +FROM ejabberd/mix as builder +ARG VERSION +ENV VERSION=${VERSION:-latest} \ + MIX_ENV=prod +LABEL maintainer="ProcessOne " \ + product="Ejabberd Community Server builder" + +# Get ejabberd sources, dependencies, configuration +RUN git clone https://github.com/processone/ejabberd.git +WORKDIR /ejabberd +COPY vars.config . +COPY rel/*exs rel/ +RUN git checkout ${VERSION/latest/HEAD} \ + && mix deps.get + +# Compile +RUN mix do compile, release.init, release --env=prod + +# Prepare runtime environment +RUN mkdir runtime \ + && tar -C runtime -zxf _build/prod/rel/ejabberd/releases/*/ejabberd.tar.gz \ + && cd runtime \ + && cp releases/*/start.boot bin \ + && echo 'beam_lib:strip_files(filelib:wildcard("lib/*/ebin/*beam")), init:stop().' | erts*/bin/erl -boot start_clean >/dev/null \ + && mv erts*/bin/* bin \ + && rm -rf releases erts* bin/*src bin/dialyzer bin/typer \ + && rm bin/ejabberd bin/ejabberd.bat bin/ejabberd_loader.sh + +# Runtime container FROM alpine:3.7 ARG VERSION ENV TERM=xterm \ @@ -14,37 +43,32 @@ LABEL maintainer="ProcessOne " \ # Create directory structure and user for ejabberd RUN addgroup ejabberd -g 9000 \ && adduser -s /bin/sh -D -G ejabberd ejabberd -u 9000 \ - && mkdir -p /home/ejabberd/config /home/ejabberd/db /home/ejabberd/log \ + && mkdir -p /home/ejabberd/conf /home/ejabberd/database /home/ejabberd/logs \ && chown -R ejabberd:ejabberd /home/ejabberd # Install required dependencies RUN apk upgrade --update musl \ && apk add \ - bash \ - ca-certificates \ - curl \ expat \ libstdc++ \ ncurses-libs \ openssl \ sqlite \ - uthash \ yaml \ zlib \ - && rm -rf /var/cache/apk/* \ - && update-ca-certificates + && rm -rf /var/cache/apk/* # Install ejabberd -ADD ejabberd-$VERSION.tar.gz $HOME -COPY ejabberd-api ejabberdctl $HOME/bin/ -COPY --chown=ejabberd:ejabberd config/* $HOME/config/ -COPY docker-entrypoint.sh / +WORKDIR $HOME +COPY --from=builder /ejabberd/runtime . +COPY bin/* bin/ +COPY --chown=ejabberd:ejabberd conf conf/ +ADD --chown=ejabberd:ejabberd https://curl.haxx.se/ca/cacert.pem conf/cacert.pem # Setup runtime environment USER ejabberd -WORKDIR $HOME -VOLUME ["$HOME/db","$HOME/config","$HOME/log"] +VOLUME ["$HOME/database","$HOME/conf","$HOME/logs"] EXPOSE 5222 5269 5280 -ENTRYPOINT ["/docker-entrypoint.sh"] -CMD ["ejabberd"] +ENTRYPOINT ["/home/ejabberd/bin/ejabberdctl"] +CMD ["foreground"] diff --git a/ecs/README.md b/ecs/README.md index 64017c8..336536b 100644 --- a/ecs/README.md +++ b/ecs/README.md @@ -1,4 +1,4 @@ -## ejabberd Community Edition - Base +## ejabberd Community Server - Base This ejabberd Docker image allows you to run a single node ejabberd instance in a Docker container. @@ -28,20 +28,26 @@ docker restart ejabberd ### Creating admin user -When the container is running (and thus ejabberd), you can exec commands inside the container. The ejabberd-api command-line tool can be used to exercise the API directly from the container, even if the API is not exposed to the outside world. +When the container is running (and thus ejabberd), you can exec commands inside the container. The api command-line tool can be used to exercise the API directly from the container, even if the API is not exposed to the outside world. Note: ejabberd configuration must allow api calls from loopback interface. To create an admin user (or any other user), you can use the following command: ```bash -docker exec -it ejabberd /home/ejabberd/bin/ejabberd-api register --endpoint=http://127.0.0.1:5280/ --jid=admin@localhost --password=passw0rd +docker exec -it ejabberd bin/ejabberdapi register --endpoint=http://127.0.0.1:5280/ --jid=admin@localhost --password=passw0rd +``` + +It's also possible to fallback to ejabberdctl commands: + +```bash +docker exec -it ejabberd bin/ejabberdctl register admin localhost passw0rd ``` ### Running ejabberd with Erlang console attached -If you would like to run it with console attached you can use the `console` command: +If you would like to run it with Erlang console attached you can use the `live` command: ```bash -docker run -it -p 5222:5222 ejabberd/ecs console +docker run -it -p 5222:5222 ejabberd/ecs live ``` This command will use default configuration file and XMPP domain "localhost". @@ -51,16 +57,32 @@ This command will use default configuration file and XMPP domain "localhost". The following command will pass config file using Docker volume feature and share local directory to store database: ```bash -mkdir db -docker run -d --name ejabberd -v $(pwd)/ejabberd.yml:/home/ejabberd/cfg/ejabberd.yml -v $(pwd)/db:/home/ejabberd/db -p 5222:5222 ejabberd/ecs +mkdir database +docker run -d --name ejabberd -v $(pwd)/ejabberd.yml:/home/ejabberd/conf/ejabberd.yml -v $(pwd)/database:/home/ejabberd/database -p 5222:5222 ejabberd/ecs +``` + +### Checking ejabberd log files + +You can execute a Docker command to check the content of the log files from inside to container, even if you do not put it on a shared persistent drive: + +```bash +docker exec -it ejabberd tail -f logs/ejabberd.log ``` -### Checking ejabberd log file +### Open ejabberd debug console -You can execute a Docker command to check the content of the log file from inside to container, even if you do not put it on a shared persistent drive: +You can open a live debug Erlang console attached to a running container: ```bash -docker exec -it ejabberd /usr/bin/tail -f /home/ejabberd/log/ejabberd.log +docker exec -it ejabberd bin/ejabberdctl debug +``` + +### Execute ejabberdctl command + +You can run anu ejabberdctl command inside running container. Example: + +```bash +docker exec -it ejabberd bin/ejabberdctl status ``` ## Docker image advanced configuration @@ -80,9 +102,9 @@ This is the kind of data you probably want to store on a persistent or local dri Here are the volume you may want to map: -- /home/ejabberd/log/: Directory containing log files -- /home/ejabberd/db/: Directory containing Mnesia database. You should backup or export the content of the directory to persistent storage (host storage, local storage, any storage plugin) -- /home/ejabberd/config/: Directory containing configuration and certificates +- /home/ejabberd/logs/: Directory containing log files +- /home/ejabberd/database/: Directory containing Mnesia database. You should backup or export the content of the directory to persistent storage (host storage, local storage, any storage plugin) +- /home/ejabberd/conf/: Directory containing configuration and certificates ## Generating ejabberd release @@ -94,16 +116,22 @@ The configuration of ejabberd Erlang/OTP release is customized with: - rel/config.exs: Customize ejabberd release - rel/dev.exs: ejabberd environment configuration for development release -- rel/docker.exs: ejabberd environment configuration for production Docker release -- config/ejabberd.yml: ejabberd default config file +- rel/prod.exs: ejabberd environment configuration for production Docker release +- vars.config: ejabberd compilation configuration options +- conf/ejabberd.yml: ejabberd default config file + +Build ejabberd Community Server base image from ejabberd master on Github: + +```bash +docker build -t ejabberd/ecs . +``` -Run the build script to generate ejabberd Community Server base image from ejabberd master on Github: +Build ejabberd Community Server base image for a given ejabberd version: ```bash -./build.sh +docker build --build-arg VERSION=18.01 -t ejabberd/ecs:18.01 . ``` ### TODO -- Embed command-line tool for ejabberd API to be able to create admin user for ejabberd. -- Rebuild last version of ejabberd-api tool when creating container. +- Rebuild last version of bin/ejabberdapi tool when creating container. diff --git a/ecs/ejabberd-api b/ecs/bin/ejabberdapi similarity index 62% rename from ecs/ejabberd-api rename to ecs/bin/ejabberdapi index 722b7b3..7ae0289 100755 Binary files a/ecs/ejabberd-api and b/ecs/bin/ejabberdapi differ diff --git a/ecs/ejabberdctl b/ecs/bin/ejabberdctl similarity index 93% rename from ecs/ejabberdctl rename to ecs/bin/ejabberdctl index 2229680..451acba 100755 --- a/ecs/ejabberdctl +++ b/ecs/bin/ejabberdctl @@ -9,26 +9,27 @@ ERL_MAX_ETS_TABLES=1400 FIREWALL_WINDOW="4370-4379" INET_DIST_INTERFACE="" ERLANG_NODE=ejabberd@$(hostname -s) +EJABBERD_BYPASS_WARNINGS=true # define default environment variables ROOT_DIR="/home/ejabberd" HOME_DIR="$ROOT_DIR" -ERL="$ROOT_DIR"/erts-9.1.5/bin/erl -IEX="$ROOT_DIR"/erts-9.1.5/bin/iex -EPMD="$ROOT_DIR"/erts-9.1.5/bin/epmd +ERL="$ROOT_DIR"/bin/erl +IEX="$ROOT_DIR"/bin/iex +EPMD="$ROOT_DIR"/bin/epmd INSTALLUSER=ejabberd # check the proper system user is used case $(id -un) in "$INSTALLUSER") EXEC_CMD="as_current_user" - [ -e "$HOME"/config/ejabberd.yml ] && HOME_DIR="$HOME" + [ -e "$HOME"/conf/ejabberd.yml ] && HOME_DIR="$HOME" ;; root) if [ -n "$INSTALLUSER" ] ; then EXEC_CMD="as_install_user" HOME=$(su - ejabberd -c pwd) - [ -e "$HOME"/config/ejabberd.yml ] && HOME_DIR="$HOME" + [ -e "$HOME"/conf/ejabberd.yml ] && HOME_DIR="$HOME" else EXEC_CMD="as_current_user" echo "WARNING: This is not recommended to run ejabberd as root" >&2 @@ -61,15 +62,15 @@ for arg; do done # define ejabberd variables if not already defined from the command line -: "${ETC_DIR:="$HOME_DIR/config"}" -: "${LOGS_DIR:="$HOME_DIR/log"}" -: "${SPOOL_DIR:="$HOME_DIR/db"}" +: "${ETC_DIR:="$HOME_DIR/conf"}" +: "${LOGS_DIR:="$HOME_DIR/logs"}" : "${EJABBERD_CONFIG_PATH:="$ETC_DIR/ejabberd.yml"}" : "${EJABBERDCTL_CONFIG_PATH:="$ETC_DIR/ejabberdctl.cfg"}" [ -f "$EJABBERDCTL_CONFIG_PATH" ] && . "$EJABBERDCTL_CONFIG_PATH" [ -n "$ERLANG_NODE_ARG" ] && ERLANG_NODE="$ERLANG_NODE_ARG" [ "$ERLANG_NODE" = "${ERLANG_NODE%.*}" ] && S="-s" : "${EJABBERD_LOG_PATH:="$LOGS_DIR/ejabberd.log"}" +: "${SPOOL_DIR:="$HOME_DIR/database/$ERLANG_NODE"}" # define erl parameters ERLANG_OPTS="+K $POLL -smp $SMP +P $ERL_PROCESSES $ERL_OPTIONS" @@ -289,11 +290,13 @@ case $1 in ;; debug) debugwarning - exec_erl "$(uid debug)" -hidden -remsh "$ERLANG_NODE" + exec_erl "$(uid debug)" -hidden -remsh "$ERLANG_NODE" \ + -boot start_clean ;; etop) exec_erl "$(uid top)" -hidden -node "$ERLANG_NODE" -s etop \ - -s erlang halt -output text + -s erlang halt -output text \ + -boot start_clean ;; iexdebug) debugwarning @@ -308,7 +311,8 @@ case $1 in [ "$PEER" = "${PEER%.*}" ] && PS="-s" exec_cmd "$ERL" ${PS:--}name "$(uid ping "$(hostname $PS)")" $ERLANG_OPTS \ -noinput -hidden -eval 'io:format("~p~n",[net_adm:ping('"'$PEER'"')])' \ - -s erlang halt -output text + -s erlang halt -output text \ + -boot start_clean ;; started) wait_status 0 30 2 # wait 30x2s before timeout @@ -317,8 +321,8 @@ case $1 in wait_status 3 30 2 && stop_epmd # wait 30x2s before timeout ;; *) - exec_erl "$(uid ctl)" -hidden -noinput -s ejabberd_ctl \ - -extra "$ERLANG_NODE" $NO_TIMEOUT "$@" + exec_erl "$(uid ctl)" -hidden -noinput -boot start_clean \ + -s ejabberd_ctl -extra "$ERLANG_NODE" $NO_TIMEOUT "$@" result=$? case $result in 2|3) help;; diff --git a/ecs/bin/erl b/ecs/bin/erl new file mode 100755 index 0000000..b0b9e7e --- /dev/null +++ b/ecs/bin/erl @@ -0,0 +1,12 @@ +#!/bin/sh +set -e + +ROOTDIR=/home/ejabberd +BINDIR=$ROOTDIR/bin +EMU=beam +PROGNAME=`echo $0 | sed 's/.*\\///'` +export EMU +export ROOTDIR +export BINDIR +export PROGNAME +exec "$BINDIR/erlexec" ${1+"$@"} diff --git a/ecs/build.sh b/ecs/build.sh deleted file mode 100755 index 4cdb706..0000000 --- a/ecs/build.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash - -VERSION=${1:-HEAD} -REF=$VERSION -[ "$VERSION" = "HEAD" ] && VERSION=latest -ARCHIVE=ejabberd-${VERSION}.tar.gz - -GREEN='\033[0;32m' -NC='\033[0m' # No Color]]' - -docker images | grep -q "ejabberd/mix" || { - echo -e "${GREEN}Pulling ejabberd build Docker image${NC}" - docker pull ejabberd/mix -} - -if [ ! -d ejbuild ]; then - echo -e "${GREEN}Cloning ejabberd${NC}" - git clone https://github.com/processone/ejabberd.git ejbuild -else - echo -e "${GREEN}Fetch ejabberd${NC}" - (cd ejbuild; git checkout master && git pull) -fi -cat > ejbuild/vars.config <LXTD8,g;xBu`.i]tq7Dz.m2?ZqO