[1] Skip to Main Content [2] Viget • [3] Work • [4] Services • [5] Articles • [6] Careers • [7] Contact • Open Menu Navigation [9] Viget Close • Practice • [11] Work • [12] Services • [13] Articles We’re a full-service digital agency that’s been helping clients make lasting change since 1999. [14] Contact Us People • [15]Company • [16]Careers • [17]Code of Ethics • [18]Diversity & Inclusion More • [19]Pointless Corp. • [20]Explorations • [21]Code at Viget Featured [22] Read the Article: Building the Future, One Intern at a Time Newsletter Building the Future, One Intern at a Time [23] Read the Article: Some Thoughts after a Major Ruby on Rails Upgrade Article Some Thoughts after a Major Ruby on Rails Upgrade Docker + Rails: Solutions to Common Hurdles [eyJidWNrZXQiOiJ2Z3QtdmlnZXRjb20tYW] • [24]Home • [25]Articles • [26]Docker + Rails: Solutions to Common Hurdles [27] Subscribe (opens in a new window) Share • [29] Share this page • [30] Share this page • [31] Post this page Eli Fatsi, Former Development Director Article Categories: [32] #Code, [33] #Back-end Engineering Posted on March 30, 2021 • [34] Share • [35] Share • [36] Post Tips n Tricks for working with Rails applications in Docker T i p s n T r i c k s f o r w o r k i n g w i t h R a i l s a p p l i c a t i o n s i n D o c k e r This is the follow on post to an earlier post: [37]Docker: Right for Us. Right for You? Docker has made a number of large problems go away, and replaced them with (usually) (hopefully) a smaller set of its own problems. Sometimes it's not worth it to make that sacrifice, but it often is for us, and here are the tricks we've picked up for working with Rails sites and Docker Compose: Rails Tips & Tricks [38]# db host Trying to docker-ify a Rails app and running into this? could not connect to server: No such file or directory Is the server running locally and accepting connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"? Make sure you have a db service defined in docker-compose.yml, and add host: db to your database.yml file. All of the services you define in the compose file become network-addressable names to each other. So adding host: db tells Rails that the hostname of the database server is db, which should point to your database service. ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ binding.pry AKA the one tool I use the most by far I gotta have it. TLDR on the solution: [39]https://stackoverflow.com/questions/35211638/ how-to-debug-a-rails-app-in-docker-with-pry/37264588#37264588 The gist is that you need to add some Docker Compose flags to the service you want to run a pry inside, and then docker attach [running_container_name] after you've started the service container. ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ save_and_open_page If you're testing w/ Capybara and want to get a glimpse of your site while a feature test is running, then Docker is going to make that difficult for you. TLDR - [40]https://github.com/copiousfreetime/launchy/issues/108# issuecomment-319644326 And the gist? You need to configure a volume so screenshots saved on the Docker container are accessible to the host machine. You then need to rig up guard locally to watch the volume directory and automatically open any HTML files that land there. ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ cacheing bundler and npm builds If you don't configure this properly, you could find yourself re-installing dependencies every time you spin up your containers. We lean on persisted volumes for this, and pick up the log and tmp directories while we're at it. like so: - services - app: entrypoint: ./.docker-config/entrypoint.sh volumes: - ./node_modules:/usr/src/app/node_modules - gems:/usr/local/bundle - log:/usr/src/app/log - tmp:/usr/src/app/tmp I'll also point out that we prefer to move the dependency installation steps into an entrypoint script, instead of within the Dockerfile build definition. This means that we're rarely rebuilding our baseline image (unless something deeper level changes, like needing an additional runtime available), and our dependencies are kept up to date everytime we cycle the containers. Here's an example of an entrypoint script for an app with Ruby gems and NPM packages: #!/bin/bash set -e # Ensure PID is reset. This can happen if docker isn't cleanly shut down. rm -rf /usr/src/app/tmp/pids # Verify node_modules are up to date yarn install --silent # Verify gems are up to date if ! bundle check > /dev/null; then echo "Gems dependencies are out of date. Installing..." bundle install fi exec "$@" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ asset performance Out of the box, sites that run perfectly quickly locally would take a lonnnnng time to respond to local asset requests. One solution we settled on was to add :delegated to the volume dedicated to syncing the codebase. For example: app: image: ruby:3.0 command: rails server -p 3000 -b '0.0.0.0' ports: - 3000:3000 volumes: # Ensure changes to the codebase are picked up by the docker container # The `:delegated` here is a critical config for speedy development - .:/usr/src/app:delegated • The docs have a lot to say about this if you want to learn more: [41]http:/ /docs.docker.oeynet.com/docker-for-mac/osxfs-caching/ • And this StackOverflow answer has a good recap in case that docs link goes down: [42]https://stackoverflow.com/a/63437557/1655658 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Running bash This one took me a while to figure out as I was learning the difference between a running Docker container and a service and an image and a volume. Once I had a clearer picture of how Docker (and Docker Compose) worked, opening up a shell into a running thing stopped being tricky. Here's what I've picked up though, hopefully these words mean something to you: If you have a running container based off of a docker-compose service, you can bash into it like so: docker-compose exec [name-of-service] bash If you have a non-running container based off of a docker-compose service, you can bash into it like so: docker-compose run --rm [name-of-service] bash The difference here is exec vs run --rm. You can probably guess what each does. The --rm flag is important so that the newly spun up containers don't hang around forever after you close out of the session. ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ importing database dumps If you're running something like PostgreSQL within Docker, it becomes a bit trickier to psql your way in from a local command line. As is often the case with Docker, there are a few ways to get the job done here, and the one that's right for you is dependent on what you're trying to do. One path is to requiring you to expose a port and run commands through that port. This can be done in a docker-compose.yml: services: db: image: mdillon/postgis:11-alpine ports: # Expose Postgres to host networking (your computer) at port 5433. # This prevents conflicts with Postgres installed on your machine # while still allowing the database to be browsed at port 5432 - 5433:5432 volumes: - db-data:/var/lib/postgresql/data Another option is to define a new volume within your database service which makes a database dump on your local machine accessible to the running Docker container. If you had a database dump stored within your project directory at . /local/db-backups, you could make it accessible within Docker like so: services: db: image: mdillon/postgis:11-alpine volumes: - db-data:/var/lib/postgresql/data - ./local/db-backups:/app/db-backups Then, bash into the running container and have at it with all your usual psql moves. Note: I'm including the db-data volume definition to point out that we always have a persistent volume configured for database services so the data persists when the containers are wound down. ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Using local SSH credentials on Docker container We have a lot of deploy processes that lean on SSH private keys for authorization. If you attempt to run one of those commands in a running Docker container, it'll fail due to it's sandboxed environment not being able to reach out into your local machine for the credentials. This is our Docker Compose solution for that: services: app: ... volumes: - type: bind source: /run/host-services/ssh-auth.sock target: /run/host-services/ssh-auth.sock The End [43]# That's about all I could recall now that it's been ~1.5 years since digging in on my own Docker journey. Hopefully something in there was useful to you. If you have another tip or trick that solved an early challenge, drop a line in the comments below! Related Articles • [44] Some Thoughts after a Major Ruby on Rails Upgrade Article Some Thoughts after a Major Ruby on Rails Upgrade Noah Over • [45] Setting up a Python Project Using asdf, PDM, and Ruff Article Setting up a Python Project Using asdf, PDM, and Ruff Danny Brown • [46] Craft 5: What It Means For Super Table Page Builders Article Craft 5: What It Means For Super Table Page Builders Max Myers The Viget Newsletter Nobody likes popups, so we waited until now to recommend our newsletter, featuring thoughts, opinions, and tools for building a better digital world. [47]Read the current issue. [48]Subscribe Here (opens in new window) Site Footer Have an unsolvable problem or audacious idea? Let’s get to work [49] Contact Us [50] hello@viget.com [51] 703.891.0670 • Practice • [52]Work • [53]Services • [54]Articles • People • [55]Company • [56]Careers • [57]Code of Ethics • [58]Diversity & Inclusion • More • [59]Pointless Corp. • [60]Explorations • [61]Code at Viget Sign Up For Our Newsletter A curated periodical featuring thoughts, opinions, and tools for building a better digital world. [62] Check it out Social Links [63] Viget • [64] • [65] • [66] • [67] • [68] • [69] Viget rhymes with 'dig it'. Click here to hear how we say it. Office Locations • [71]Washington, DC Metro • [72]Durham, NC • [73]Boulder, CO • [74]Chattanooga, TN © 1999 – 2024 Viget Labs, LLC. [75]Terms [76]Privacy [77]MRF References: [1] https://www.viget.com/articles/docker-rails-solutions-to-common-hurdles/#content [2] https://www.viget.com/ [3] https://www.viget.com/work/ [4] https://www.viget.com/services/ [5] https://www.viget.com/articles/ [6] https://www.viget.com/careers/ [7] https://www.viget.com/contact/ [9] https://www.viget.com/ [11] https://www.viget.com/work/ [12] https://www.viget.com/services/ [13] https://www.viget.com/articles/ [14] https://www.viget.com/contact/ [15] https://www.viget.com/about/ [16] https://www.viget.com/careers/ [17] https://www.viget.com/code-of-ethics/ [18] https://www.viget.com/diversity-equity-and-inclusion/ [19] https://pointlesscorp.com/ [20] https://explorations.viget.com/ [21] https://code.viget.com/ [22] https://www.viget.com/newsletter/building-the-future-one-intern-at-a-time/ [23] https://www.viget.com/articles/some-thoughts-after-a-major-ruby-on-rails-upgrade/ [24] https://www.viget.com/ [25] https://www.viget.com/articles [26] https://www.viget.com/articles/docker-rails-solutions-to-common-hurdles/#hero [27] http://eepurl.com/gtHqsj [29] https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fwww.viget.com%2Farticles%2Fdocker-rails-solutions-to-common-hurdles%2F [30] http://www.linkedin.com/shareArticle?mini=true&url=https%3A%2F%2Fwww.viget.com%2Farticles%2Fdocker-rails-solutions-to-common-hurdles%2F [31] https://x.com/intent/tweet?text=Tips%20n%20Tricks%20for%20working%20with%20Rails%20applications%20in%20Docker%20https%3A%2F%2Fwww.viget.com%2Farticles%2Fdocker-rails-solutions-to-common-hurdles%2F [32] https://www.viget.com/articles/?category=code#results [33] https://www.viget.com/articles/?category=back-end-engineering#results [34] https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fwww.viget.com%2Farticles%2Fdocker-rails-solutions-to-common-hurdles%2F [35] http://www.linkedin.com/shareArticle?mini=true&url=https%3A%2F%2Fwww.viget.com%2Farticles%2Fdocker-rails-solutions-to-common-hurdles%2F [36] https://x.com/intent/tweet?text=Tips%20n%20Tricks%20for%20working%20with%20Rails%20applications%20in%20Docker%20https%3A%2F%2Fwww.viget.com%2Farticles%2Fdocker-rails-solutions-to-common-hurdles%2F [37] https://www.viget.com/articles/docker-right-for-us-right-for-you-1 [38] https://www.viget.com/articles/docker-rails-solutions-to-common-hurdles/#rails-tips-tricks [39] https://stackoverflow.com/questions/35211638/how-to-debug-a-rails-app-in-docker-with-pry/37264588#37264588 [40] https://github.com/copiousfreetime/launchy/issues/108#issuecomment-319644326 [41] http://docs.docker.oeynet.com/docker-for-mac/osxfs-caching/ [42] https://stackoverflow.com/a/63437557/1655658 [43] https://www.viget.com/articles/docker-rails-solutions-to-common-hurdles/#the-end [44] https://www.viget.com/articles/some-thoughts-after-a-major-ruby-on-rails-upgrade/ [45] https://www.viget.com/articles/setting-up-a-python-project-using-asdf-pdm-and-ruff/ [46] https://www.viget.com/articles/craft-5-what-it-means-for-super-table-page-builders/ [47] https://www.viget.com/newsletter [48] http://eepurl.com/gtHqsj [49] https://www.viget.com/contact/ [50] mailto:hello@viget.com?subject=Hello%2C%20Viget%21 [51] tel:7038910670 [52] https://www.viget.com/work/ [53] https://www.viget.com/services/ [54] https://www.viget.com/articles/ [55] https://www.viget.com/about/ [56] https://www.viget.com/careers/ [57] https://www.viget.com/code-of-ethics/ [58] https://www.viget.com/diversity-equity-and-inclusion/ [59] https://pointlesscorp.com/ [60] https://explorations.viget.com/ [61] https://code.viget.com/ [62] https://www.viget.com/newsletter/ [63] https://www.viget.com/ [64] http://x.com/viget [65] https://github.com/vigetlabs [66] https://dribbble.com/viget [67] https://www.instagram.com/viget/ [68] https://www.linkedin.com/company/viget-labs [69] https://vimeo.com/viget/collections [71] https://www.viget.com/dc-metro-hq/ [72] https://www.viget.com/durham/ [73] https://www.viget.com/boulder/ [74] https://www.viget.com/chattanooga/ [75] https://www.viget.com/terms-conditions/ [76] https://www.viget.com/privacy-policy/ [77] https://individual.carefirst.com/individuals-families/mandates-policies/machine-readable-file.page