Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sharing precompiled assets across docker containers

Tags:

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?

like image 901
tomasbasham Avatar asked Mar 09 '15 20:03

tomasbasham


People also ask

Can 2 containers communicate with each other?

If you are running more than one container, you can let your containers communicate with each other by attaching them to the same network. Docker creates virtual networks which let your containers talk to each other. In a network, a container has an IP address, and optionally a hostname.

Do Docker containers share resources?

Docker containers all run in the same kernel, vs a VM which runs a kernel per guest. So, in terms of which resources in the kernel are shared... really, that would be absolutely everything, except those items which are namespaced away from each other (non-shared mounts, process tree entries, cgroups, etc).

Can a Docker volume be shared between containers?

Volumes are easier to back up or migrate than bind mounts. You can manage volumes using Docker CLI commands or the Docker API. Volumes work on both Linux and Windows containers. Volumes can be more safely shared among multiple containers.


1 Answers

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.

like image 145
Fábio Batista Avatar answered Oct 28 '22 00:10

Fábio Batista