tiagodavi

tiagodavi

Hi Guys. I have elixir/phoenix running inside a docker container with docker compose and I realised my project takes much more time to run tests inside docker and it’s needed to compile every single time I run my tests, even by running just one test.

Does anyone know how to solve this problem?

Thanks.

docker-compose.yml

version: "3.4"
services:
  db:
    image: "mdillon/postgis"
    volumes:
      - db_store:/var/lib/postgresql/data
    ports:
      - "5432:5432"

  redis:
    image: "redis:5.0"

  web:
    build:
      context: .
      target: build
      args:
        MIX_ENV: "dev"
    command: '/bin/bash -c "while true; do sleep 10; done;"'
    volumes:
      - .:/opt/app
      - ./priv/ua_inspector:/opt/data/ua_inspector
      - build_cache:/opt/cache
      - elixir_mix:/root/.mix
    depends_on:
      - db
      - redis
    ports:
      - "4000:4000"
    ulimits:
      nofile: 1024
      # memlock: 64
      nproc: 63090
    environment:
      - LOCAL_USER_ID=${LOCAL_USER_ID}
    env_file: .env.development
    tty: true
    stdin_open: true

volumes:
  db_store: {}
  build_cache: {}
  elixir_mix: {}

Dockerfile

#########################################################
## BUILD STAGE - Development image with necessary deps ##
#########################################################

FROM verybigthings/elixir:1.8 AS build

ARG WORKDIR=/opt/app
ARG MIX_ENV=prod
ARG APP_USER=user

ENV MIX_ENV=${MIX_ENV}
ENV WORKDIR=$WORKDIR
ENV APP_USER=$APP_USER
ENV MIX_HOME=/opt/cache/mix
ENV HEX_HOME=/opt/cache/hex
ENV BUILD_PATH=/opt/cache/_build
ENV DEPS_PATH=/opt/cache/deps

RUN apt-get update \
  && apt-get install -y \
  #  wkhtmltopdf \
  xvfb \
  libssl1.0-dev \
  && apt-get clean \
  && rm -rf /var/lib/apt/lists/*

RUN wget https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.4/wkhtmltox-0.12.4_linux-generic-amd64.tar.xz
RUN tar vxf wkhtmltox-0.12.4_linux-generic-amd64.tar.xz
RUN cp wkhtmltox/bin/wk* /usr/local/bin/

RUN apt-get update && apt-get install -y \
  make vim less bash git locales inotify-tools postgresql-client

# Tool to propagate singals from the container to the app
ENV PID1_VERSION=0.1.2.0
RUN curl -sSL "https://github.com/fpco/pid1/releases/download/v${PID1_VERSION}/pid1-${PID1_VERSION}-linux-x86_64.tar.gz" | tar xzf - -C /usr/local \
  && chown root:root /usr/local/sbin \
  && chown root:root /usr/local/sbin/pid1

WORKDIR $WORKDIR

RUN mix local.hex --force && \
  mix local.rebar --force

# Set entrypoint
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]

CMD ["/bin/bash", "-c", "while true; do sleep 10; done;"]

######################################################################################
## PRE-RELEASE STAGE - compiles code and bundles the application to Erlang release  ##
######################################################################################

FROM build AS pre-release

ARG APP_NAME
ARG APP_VSN

ENV APP_NAME=${APP_NAME} \
  APP_VSN=${APP_VSN}

COPY . .

ENV PHOENIX_VERSION 1.4.3
RUN mix archive.install hex phx_new $PHOENIX_VERSION --force

RUN mkdir -p /opt/built \
  && mix do deps.get, compile --warnings-as-errors \
  && cd assets\
  && yarn install && yarn build \
  && cd .. \
  && mix do phx.digest, release --verbose \
  && cp /opt/cache/_build/${MIX_ENV}/rel/${APP_NAME}/releases/${APP_VSN}/${APP_NAME}.tar.gz /opt/built \
  && cd /opt/built \
  && tar -xzf ${APP_NAME}.tar.gz \
  && rm ${APP_NAME}.tar.gz

############################################
## RELEASE STAGE - production application ##
############################################

FROM debian:9-slim AS release

RUN apt-get update \
  && apt-get install -y \
  libssl1.0-dev \
  wget \
  xz-utils \
  libxrender1 \
  libfontconfig \
  libxext6 \
  && apt-get clean \
  && rm -rf /var/lib/apt/lists/*

RUN wget https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.4/wkhtmltox-0.12.4_linux-generic-amd64.tar.xz
RUN tar vxf wkhtmltox-0.12.4_linux-generic-amd64.tar.xz
RUN cp wkhtmltox/bin/wk* /usr/local/bin/

# Install Aptible CLI tool.
RUN wget https://omnibus-aptible-toolbelt.s3.amazonaws.com/aptible/omnibus-aptible-toolbelt/master/187/pkg/aptible-toolbelt_0.16.2%2B20190829193224~ubuntu.16.04-1_amd64.deb
RUN dpkg -i aptible-toolbelt_0.16.2+20190829193224~ubuntu.16.04-1_amd64.deb

ARG APP_NAME

ENV LANG C.UTF-8
ENV LC_ALL C.UTF-8

RUN apt-get update && apt-get install -y \
  bash git libpq-dev libjson-c-dev

ENV REPLACE_OS_VARS=true \
  APP_NAME=${APP_NAME} 

WORKDIR /opt/app

COPY ./priv/ua_inspector /opt/data/ua_inspector
COPY --from=pre-release /opt/built .

EXPOSE 4000

CMD trap 'exit' INT; /opt/app/bin/${APP_NAME} foreground

Showing Posts 1 to 10

Exadra37

Exadra37

Please add your Dockerfile and docker-compose.yml files to your topic so that we can try to figure out what’s going on.

Please also remember to say if you are on Linux, Windows or Mac.

tiagodavi

tiagodavi OP

Thank you. I will

tiagodavi

tiagodavi OP

I put Dockerfile and docker-compose.yml

Exadra37

Exadra37

You are using a Dockerfile for build a production release. This is not suitable for development use.

You need to drop a Dockerfile with stages and build everything in one stage.

Also you need to map your entire workdir in the host, and always work inside the docker container.

If you use Elixir in the host and then use inside the docker container you may get weird results because of mismatch in versions of Elixir/Phoenix/Erlang.

See an example in a old learning project of mine:

Dockerfile:

FROM elixir:1.3.4

# Inspired in: http://davidanguita.name/articles/dockerizing-a-phoenix-project/

ARG CONTAINER_USER='elixir'

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update && \
    apt-get -y upgrade && \
    apt-get -y install \
        apt-utils \
        locales \
        curl \
        less \
        git \
        zsh && \
    apt install -f && \
    locale-gen en_GB.UTF-8 && \
    dpkg-reconfigure locales && \

    # Intall Oh My Zsh for root user
    bash -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)" && \

    useradd -m -u 1000 -s /usr/bin/zsh "${CONTAINER_USER}" && \
    su "${CONTAINER_USER}" -c 'bash -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"' && \

    # Install NodeJS 6.x and the NPM
    curl -sL https://deb.nodesource.com/setup_6.x | bash - && \
    apt-get install -y -q nodejs

USER "${CONTAINER_USER}"

COPY .gitconfig /home/"${CONTAINER_USER}"/.gitconfig

# This commands will run under user defined above
RUN mix local.hex --force && \
    mix local.rebar --force

# Set the workdir for the container user defined above
WORKDIR /app

docker-compose.yml:

version: "2.1"

# Inspired in: http://davidanguita.name/articles/dockerizing-a-phoenix-project/

services:
  build:
    build: ./docker
    image: exadra37/elixir
    env_file: .env
    volumes_from:
      - app

  shell:
    image: exadra37/elixir
    env_file: .env
    environment:
      - MIX_ENV=dev
    depends_on:
      postgres:
        condition: service_healthy
    links:
      - build
    ports:
      - "4000:4000"
    command:
      - zsh
    volumes_from:
      - app
    volumes:
      - ${SHELL_SSH_VOLUME_MAP:-~/.ssh:/home/elixir/.ssh}
      - ${SHELL_GIT_CONFIG_VOLUME_MAP:-~/.gitconfig:/home/elixir/.gitconfig}

  iex:
    build: ./docker
    image: ${IEX_IMAGE:-exadra37/elixir:1.3.4}
    env_file: .env
    environment:
      - MIX_ENV=dev
    command:
      - iex
    volumes_from:
      - app

  web:
    build: ./docker/build/web
    image: ${WEB_IMAGE:-exadra37/phoenix:1.3.0}
    env_file: .env
    environment:
      - MIX_ENV=dev # That's the environment mode, you know
    depends_on:
      postgres:
        condition: service_healthy
    volumes_from:
      - app
    ports:
      - "4000:4000"
    links:
      - build

  app:
    image: tianon/true
    volumes:
      - ./:/app

  postgres:
    image: postgres
    env_file: .env
    healthcheck:
      test: ["CMD-SHELL", "psql -h 'localhost' -U 'postgres' -c '\\l'"]
      interval: 30s
      timeout: 30s
      retries: 3
    ports:
      - "5432"

I use a much more refined Docker stack nowadays, but is not ready to share… sorry.

Anyway you can use the above as a starting point to adapt to your needs.

tiagodavi

tiagodavi OP

Thank you. I’ll try yours.

tiagodavi

tiagodavi OP

I figured out it was a Docker For Mac’s problem. So I found a library called docker-sync that improves volumes performance and everything runs much better:

Exadra37

Exadra37

Good that you speed-ed up volumes mapping, but I still stand for what I said that you are using a Dockerfile format suitable for releases, not for development.

tiagodavi

tiagodavi OP

Actually I knew this was for releases. I know I can use Alpine etc, but I am using this for a specific reason. Thanks.

cnck1387

cnck1387

Have you looked into using the edge version of Docker Desktop? It has a new way of syncing files using “Mutagen” that brings volume mount performance up to native MacOS speeds.

There’s a good speed comparison of it here: File system performance improvements · Issue #1592 · docker/for-mac · GitHub

Personally I run Windows and use Docker Desktop which is really fast so I have no first hand experience using this but other folks who use MacOS have said they’ve seen good results (I run a Docker course so I tend to keep a pulse on Docker things for every OS).

wolf4earth

wolf4earth

Alternatively you might want to look into the “consistency” options for mounts on Docker for MacOS. They exist to tune performance of mounts on MacOS.

The default here is consistent which is also the slowest option. When mounting local files into a container then I’ve made good experiences with cached:

The macOS host’s view of the mount is authoritative. There may be delays before updates made on the host are visible within a container.

Where Next? Top

Trending in Discussions Top

AstonJ
As the title says, please share what you’ve been up to with Elixir. Whether that’s been learning it, looking into it, making stuff with i...
2977 94592 917
New
cblavier
Hey there, It’s been more than a year since we started using LiveView as our main UI library and building a whole library of UI componen...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
heathen
Quite interesting article Google brought me. Didn’t find any mentions about it here. What do you think in general? Would you use togethe...
New
maennchen
:warning: Security advisory: Decimal DoS vulnerability A vulnerability has been published for decimal where very large exponents can cau...
New
marciol
It would be helpful to have a list of companies worldwide that hire engineers without prior experience in Elixir. Often, it can be quite ...
New
Null-logic-0
What IDE or editor are you using for Elixir development? Personally, I use Zed, and I really like it, but sometimes I wish there were a ...
New

Other Trending Topics Top

ancatrusca
New episode with Louis Pilfold - the most detailed conversation about Gleam’s design I’ve come across. Worth knowing for the Elixir comm...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews