maxwelld90
maxwelld90

Reputation: 1

Docker Containers: Two Services, Similar Containers

I've got two services that I wish to spin up in Docker. According to Docker's documentation, the general rule of thumb is that you should spin up each service within its own container. I understand the reasoning behind this.

However, my two services both require the same basic setup. Having two Dockerfiles for the respective services seems wasteful, especially as all that would differ is what the CMD is that runs.

My question: using docker-compose and Dockerfiles, how can I build a "common" image (where all dependencies are installed), before each CMD can be run in a separate container, using the "common" image as a starting point? I could build the "common" image and push it to a (private?) registry (from what I understand), but would multi-stage builds be the solution here?

For example, something like:

FROM python:3.8-alpine AS builder

RUN apk add --update --no-cache \
        gcc \
        libc-dev \
        libffi-dev \
        libressl-dev \
        musl-dev \
    && mkdir /usr/app/

COPY ./testproject /usr/app/testproject/
COPY ./requirements.txt /usr/app/requirements.txt

WORKDIR /usr/app

RUN pip install -r requirements.txt

~~~~

FROM python:3.8-alpine AS wss
WORKDIR /usr/app/testproject
CMD ["wsserver", "-b", "0.0.0.0", "-p", "8001", "testproject.asgi:application"]

~~~~

FROM python:3.8-alpine AS http
WORKDIR /usr/app/testproject
CMD ["httpserver", "-b", "0.0.0.0", "-p", "8000", "testproject.asgi:application"]

Obviously, this doesn't work -- I don't know how to bring the Docker artefacts over to wss or http from builder. Or I may be barking up the wrong tree. Basically, I want to be able to spin up wss or http as individual services in my docker-compose.yml file.

Indeed, in my docker-compose.yml file, documentation suggests that I could then use target: http to build the http image for that service, as an example.

Still getting the hang of Docker-ing. Thanks for any advice!

Upvotes: 0

Views: 35

Answers (1)

David Maze
David Maze

Reputation: 158812

You can easily override CMD when you run the image. In Compose, you'd use the command: setting:

version: '3.8'
services:
  wss:
    build: .
    command: wsserver -b 0.0.0.0 -p 8000 testproject.asgi:application
    ports: ['8001:8000']
  http:
    build: .
    command: httpserver -b 0.0.0.0 -p 8000 testproject.asgi:application
    ports: ['8000:8000']

I wouldn't use a multi-stage build here; if you do, though, you can use the AS name from a previous stage in the FROM line of a later stage, so say FROM builder AS ... in the last two stages. (Multi-stage builds are a little better suited to building a single final artifact, and I might argue that even having two images is a little bit overly complex.)

Upvotes: 1

Related Questions