DEV Community

DragosTrif
DragosTrif

Posted on

8

Mojolicious and Docker

This post plans to illustrate how you can build and dockerize and Mojolicious application and solve basic issue like volume mounts permission and env values.

Building an simple dockerized app

  • Prerequisites:
curl -L http://cpanmin.us | perl - App::cpanminus
cpanm --verbose Carton
Enter fullscreen mode Exit fullscreen mode

At this point we can create an cpanfile and Mojolicious and some other dependencies in it.

    requires 'Mojolicious' => '9.39', 
Enter fullscreen mode Exit fullscreen mode
  • Generate the app:
carton install
carton exec -- mojo generate app
Enter fullscreen mode Exit fullscreen mode
  • Generate the Dockerfile:
touch Dockerfile
Enter fullscreen mode Exit fullscreen mode

And populated with the following lines of code:

FROM perl:latest
LABEL version="1.0"
LABEL description="Foo Bar foo.bar@gmail.com"
# add C dependencies 
RUN apt-get update && apt-get install -y \
    build-essential \
    libssl-dev \
    libxml2-dev \
    libexpat1-dev \
    zlib1g-dev \
    libpq-dev \
    libmariadb-dev \
    mariadb-client \
    libdbd-mariadb-perl \
    ssh \
    && rm -rf /var/lib/apt/lists/*  # Clean up to reduce image size
# install Carton
RUN curl -L http://cpanmin.us | perl - App::cpanminus && \
    cpanm --notest --verbose Carton
# create a new user and group for your app 
RUN groupadd -r my_app_group && useradd -r -g my_app_group -m -d /home/my_app my_app_user
# create home dir for that user 
RUN mkdir -p /home/my_app && \
    chown -R my_app_user:my_app_group /home/my_app
# switch from root to the new user 
USER my_app_user

WORKDIR /home/my_app

ENV PATH="/home/my_app/.perl/bin:${PATH}"

# Copy application dependencies and files
COPY --chown=my_app_user:my_app_group cpanfile /home/my_app
COPY --chown=my_app_user:my_app_group cpanfile.snapshot /home/my_app

# Install dependencies using Carton
RUN carton install --deployment

EXPOSE 3000

ENTRYPOINT ["carton", "exec", "--", "morbo", "my_app/script/my_app"]
Enter fullscreen mode Exit fullscreen mode
  • Add the docker compose file:
# touch docker compose
services:
  web:
    image: my_app
    ports: 
      - "3000:3000"
    build:
      context: .
      dockerfile: Dockerfile
    working_dir: /home/my_app  # Set the working directory
    env_file:
      - .env
    volumes:
      - ./my_app:/home/my_app/my_app:ro
      - ./.env:/home/my_app/.env:ro
Enter fullscreen mode Exit fullscreen mode

Now run:

  docker compose build
  docker compose up
Enter fullscreen mode Exit fullscreen mode

The landing page for Mojolicious should be available at

http://127.0.0.1:3000
Enter fullscreen mode Exit fullscreen mode

What just happened:
We locally ran carton install and and created an local Mojo app. Running locally carton install creates the cpanfile.snapshot that it used by the Docker image to handle the Perl module versioning.
The Docker file create an base image from perl:latest, installed essential OS dependencies, used Carton to handle Perl module dependencies, created a non-root user skin_care_user with proper permissions and setup morbo server via ENTRYPOINT directive. Then compose.yaml file mounts the application and the .env file and maps the port "3000:3000"

Postmark Image

"Please fix this..."

Focus on creating stellar experiences without email headaches. Postmark's reliable API and detailed analytics make your transactional emails as polished as your product.

Start free

Top comments (2)

Collapse
 
sumu profile image
SuMu

carton install fails

Collapse
 
dragostrif profile image
DragosTrif

I you use RUN carton install --deployment you need have an cpanfile.snapshot generated before. I usually accomplish that by running carton install locally. I cloud provide more help if you provide me more details about the error.

Billboard image

Try REST API Generation for Snowflake

DevOps for Private APIs. Automate the building, securing, and documenting of internal/private REST APIs with built-in enterprise security on bare-metal, VMs, or containers.

  • Auto-generated live APIs mapped from Snowflake database schema
  • Interactive Swagger API documentation
  • Scripting engine to customize your API
  • Built-in role-based access control

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay