Compiling Static Files with docker-compose

Compiling Static Files with docker-compose

Many projects require the execution of various tool commands during deployment, such as compressing static files with gulp/grunt, and compiling with compass. These tools may encounter some difficulties during Docker deployment because usually, a single image only contains one service.

Some people use integrated images, and others choose to apt-get update && apt-get install the relevant environments, but this requires writing complex Dockerfiles, significantly prolongs the build time, and bloats the single image, which is not very Docker-like.

We can simplify this process using the volumes_from parameter of docker-compose:

volumes_from
Mount all of the volumes from another service or container, optionally specifying read-only access(ro) or read-write(rw).

Environment

Our sample environment looks something like this:

  • python (main project)
  • node (npm, bower, grunt)
  • ruby (compass)

Compiling Files

Structure

├── Dockerfile
├── DockerfileNode
├── DockerfileRuby
├── requirements.txt
├── bower.json
├── package.json
├── config.rb
├── static
│   ├── src
│   ├── dist
│   ├── ...
├── app
│   ├── ...

Dockerfile (python)

Normal python compilation, without adding node and ruby environments

FROM python
ADD . code/
RUN pip install -r requirements.txt

# Expose port 4000 to other containers
EXPOSE 4000

CMD gunicorn --chdir /code -w 4 -b 0.0.0.0:4000 apps:app

Dockerfile (node)

FROM node

ADD . /code
WORKDIR /code

RUN npm install -g bower grunt-cli
RUN bower install --allow-root

RUN npm install

# Expose /code directory to other containers, this command must be added for using volumes_from
VOLUME /code
CMD grunt

Here we use the node image to install node-related environments, and mark the code directory as a volume

Dockerfile (ruby)

FROM ruby
ADD ./config.rb /config.rb
RUN gem install compass
CMD compass compile

Here we use the ruby image to install compass environment

docker-compose.yml


app:
  build: .

node:
  build: .
  dockerfile: ./DockerfileNode

compass:
  build: .
  dockerfile: ./DockerfileRuby
  # Mount the code directory from the node container, for compilation
  volumes_from:
    - node

nginx:
  image: nginx
  volumes:
    - ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
  links:
    - app
  ports:
    - 80:80
  # The app(python) container no longer mounts the static files, the static files directory is directly mounted to nginx to serve
  volumes_from:
    - node

This compose defines 4 services:

  • app
    • Main service
  • node
    • Contains bower_components
    • Contains node_modules
    • Performs grunt compilation at runtime, after which the container automatically stops
    • The /code directory inside the container is exposed for other containers to mount
  • ruby
    • Contains the compass tool
    • Mounts the /code directory from the node container, performs relevant compilations at runtime
  • nginx
    • Mounts the /code directory from the node container, which has been compiled by grunt and compass, and is served directly by nginx

This is roughly the process. Here, the compilation command is written as CMD in the Dockerfile, so it can be executed during container runtime. This is necessary for the compass image, but for the node image, it can also be written as RUN in the Dockerfile, depending on specific needs.

comments powered by Disqus