简体   繁体   中英

Sharing precompiled assets across docker containers

I have an nginx container separate from my rails container and want to be able to serve precompiled assets from rails with the nginx container. This sounds like a job for a volume container but I have got myself confused after having quickly needing to learn docker and reading the documentation endlessly. Has anybody had to deal with a similar situation?

I'm having the same issue. Here's what I'm currently working on:

Option 1: use a single image for both nginx and the app

This way, I can build the image once (with the app, precompiled assets and nginx), then run two instances of it: one running the app server, and another for the nginx frontend:

docker build -t hello .
docker run --name hello-app hello rackup
docker run --name hello-web -p 80:80 --link hello-app:app hello nginx

Not pretty, but very easy to set up and upgrade.

Option 2: use a shared volume, and precompile assets as a job

Shared volumes cannot be updated in the build process, but can be updated by a container instance. So we can run our rake task to precompile the assets just before running our app:

docker build -t hello .
docker run -v /apps/hello/assets:/app/public/assets hello rake assets:precompile
docker run --name hello-app hello rackup
docker run --name hello-web -p 80:80 --link hello-app:app -v /apps/hello/assets:/usr/share/nginx/html/assets nginx

This looks like a more robust option, but will require a more complex instrumentation. I'm leaning towards this option, however, since we'll need a separate job for database migrations anyway.

Option 3: distribute the assets to a CDN on build-time

Your Dockerfile can upload the resulting assets directly to a CDN. Then you configure your Rails app to use it as the asset_host . Something like:

RUN rake assets:precompile && aws s3 sync public/assets s3://test-assets/

I'm currently experimenting with this option. Since I'm using Amazon CloudFront, looks like I can just sync the resulting assets to S3 using the AWS CLI. There's also a gem for that ( asset_sync ), but it looks stale.

The downside is that you'll have to send the needed AWS credentials to the build context or the Dockerfile itself – this might need committing them to your source repository, if you're using an automated build.

I recommend to precompile assets inside of Docker container because in this case you can without any problems run it to any environment otherwise before run docker container you should copy shared precompilled assets to new environment, mount them and only after it run docker container.

The other problem related to version of assets. I mean that your code must use assets compatible with it otherwise you will have different problems with CSS and JS. So, this is the second point why you should precompile assets inside of Docker container.

For production, @maxd is right: you should add the compiled assets to your images. However, for development I think you are right. Use a volume container that is used by:

  • the rails container to store the precompiled assets
  • the nginx container to serve the assets

An alternative would be mounting a host directory into the containers.

You can find more help in the Managing Data in Containers User Guide

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM