I am learning Docker and would appreciate some wisdom.
My current assumption of Docker is that the Dockerfile and resulting Image build from it only store the actual environment itself. And not the application files/server. We utilize Volumes to store and run application code in a container. In a production Docker example that needs to be mounted on the fly. How does one use application code (because it's not stored in the Image... right?) in the Image itself.
When I use my Docker Image in development I start a container with a mounted volume of my local working directory. Here's my command to do that.
docker run -v $(pwd):/app image_name
1. Do I pull from GitHub in the actual Dockerfile to add and use the application code in the container?
2. Is there a way to store the application code on the Docker Image itself?
For example, this is my very simple Dockerfile:
FROM ruby:3.1.1-alpine3.15
RUN apk update -q
RUN apk add bash yarn git build-base nodejs mariadb-dev tzdata
ENV RAILS_ENV development
WORKDIR /app
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
COPY package.json /app/package.json
COPY yarn.lock /app/yarn.lock
RUN gem install bundler
RUN gem update bundler
RUN bundle install
COPY entrypoint.sh /usr/bin
RUN chmod x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000
CMD ["rails", "server", "-b", "0.0.0.0"]
Thank you in advance, any advice would be greatly appreciated.
CodePudding user response:
Dockerfile is used to create an automated build with a list of command line instuctions. You can copy the entire codebase in your image, a simple rails dockerfile is like:
FROM ruby:2.6.6-alpine
RUN apk update && apk add bash build-base nodejs postgresql-dev tzdata git openssh
RUN mkdir /project
WORKDIR /project
ENV RAILS_ENV development
COPY Gemfile Gemfile.lock ./
RUN gem install bundler --no-document
RUN bundle install --no-binstubs --jobs $(nproc) --retry 3
COPY . .
CMD ["rails", "server", "-b", "0.0.0.0"]
Here COPY . .
will copy the content of the current directory (your code) in the final image.
You can use docker-compose to build multiple images, eg. webapp db:
docker-compose.yml
services:
db:
image: 'postgres:11-alpine'
volumes:
- 'postgres:/var/lib/postgresql/data'
ports:
- '5432:5432'
environment:
- POSTGRES_HOST_AUTH_METHOD=trust
container_name: 'project-db'
restart: on-failure
web:
depends_on:
- 'db'
build:
context: .
dockerfile: ./Dockerfile
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
ports:
- '3000:3000'
environment:
- DATABASE_HOST=db
container_name: 'project-rails'
restart: on-failure
volumes:
db:
postgres:
Here you define volumes, folders to persist when image goes down.
When you first build your images (eg. docker-compose up --build
), Docker
will download base images if not already on your machine, it will build and run them.
When you update your codebase and lauch a new build, Docker
will cache unchanged images layers and rebuild only what you modified.