How to include Docker environment arguments when running docker compose? - docker

I am new to Docker / docker compose and am using it to deploy an API to a server. I found an image that I wish to use, which includes the option to add some environment variables, in particular:
GUNICORN_CMD_ARGS
Any additional command line settings for Gunicorn can be passed in the
GUNICORN_CMD_ARGS environment variable.
Read more about it in the Gunicorn docs: Settings.
These settings will have precedence over the other environment
variables and any Gunicorn config file.
For example, if you have a custom TLS/SSL certificate that you want to
use, you could copy them to the Docker image or mount them in the
container, and set --keyfile and --certfile to the location of the
files, for example:
docker run -d -p 80:8080 -e GUNICORN_CMD_ARGS="--keyfile=/secrets/key.pem --certfile=/secrets/cert.pem" -e PORT=443 myimage
I would like to add these two options (keyfile and certfile) as arguments to the docker run command, but instead pass docker compose up to create the images and run the container.
How would I go about doing that?
My Docker file is:
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.9
COPY ./requirements.txt /app/requirements.txt
RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt
COPY ./app /app
And my docker-compose.yml file is:
version: "3"
services:
backend:
build: ./
restart: always
network_mode: "host"
I have tried adding a CMD line to the end of my Docker file but to no avail.

You can use the environment key in you docker-compose.yml like this:
environment:
GUNICORN_CMD_ARGS: --keyfile=/secrets/key.pem --certfile=...
PORT: 443
https://docs.docker.com/compose/compose-file/compose-file-v3/#environment

Related

How does the command key in docker-compose file work

I am trying to understand the docker sample application 'example-voting-app'. I am trying to build the app with docker-compose. I am confused with the behaviour of 'command' key in docker compose file and the CMD Instruction in Dockerfile. The application consists of a service called 'vote'. The configuration for the vote service in docker-compose.yml file is:
services: # we list all our application services under this 'services' section.
vote:
build: ./vote # specifies docker to build the
command: python app.py
volumes:
- ./vote:/app
ports:
- "5000:80"
networks:
- front-tier
- back-tier
The configuration of the Dockerfile provided in ./vote directory is as below:
# Using official python runtime base image
FROM python:2.7-alpine
# Set the application directory
WORKDIR /app
# Install our requirements.txt
ADD requirements.txt /app/requirements.txt
RUN pip install -r requirements.txt
# Copy our code from the current folder to /app inside the container
ADD . /app
# Make port 80 available for links and/or publish
EXPOSE 80
# Define our command to be run when launching the container
CMD ["gunicorn", "app:app", "-b", "0.0.0.0:80", "--log-file", "-", "--access-logfile", "-", "--workers", "4", "--keep-alive", "0"]
My doubt here is which command ( 'python app.py' or 'gunicorn app:app -b ...') will be executed when i try building the application using docker-compose up
The Docker Compose command:, or everything in a docker run invocation after the image name, overrides the Dockerfile CMD.
If the image also has an ENTRYPOINT, the command you provide here is passed as arguments to the entrypoint in the same way the Dockerfile CMD does.
For a typical Compose setup you shouldn't need to specify a command:. In a Python/Flask context, the most obvious place it's useful is if you're also using a queueing system like Celery with the same shared code base: you can use command: to run a Celery worker off of the image you build, instead of a Flask application.

Pass environment variables from docker-compose to vue app with nginx

I want to dockerize my vuejs app and to pass it environment variables from the docker-compose file.
I suspect the app gets the environment variables only at the build stage, so it does not get the environment variables from the docker-compose.
vue app:
process.env.FIRST_ENV_VAR
Dockerfile:
FROM alpine:3.7
RUN apk add --update nginx nodejs
RUN mkdir -p /tmp/nginx/vue-single-page-app
RUN mkdir -p /var/log/nginx
RUN mkdir -p /var/www/html
COPY nginx_config/nginx.conf /etc/nginx/nginx.conf
COPY nginx_config/default.conf /etc/nginx/conf.d/default.conf
WORKDIR /tmp/nginx/vue-single-page-app
COPY . .
RUN npm install
RUN npm run build
RUN cp -r dist/* /var/www/html
RUN chown nginx:nginx /var/www/html
CMD ["nginx", "-g", "daemon off;"]
docker-compose:
version: '3.6'
services:
app:
image: myRegistry/myProject:tag
restart: always
environment:
- FIRST_ENV_VAR="first environment variable"
- SECOND_ENV_VAR="first environment variable"
ports:
- 8080:8080
Is there any way to pass environment variables to a web application after the build stage?
In vue js apps you need to pass the env variables as VUE_APP_
so in your case it should be VUE_APP_FIRST_ENV_VAR
Based on this https://medium.com/#rakhayyat/vuejs-on-docker-environment-specific-settings-daf2de660b9, I have made a silly npm package that help to acomplish what you want.
Go to https://github.com/juanise/jvjr-docker-env and take a look to README file.
Basically just run npm install jvjr-docker-env. A new Dockerfile, entrypoint and json file will be added to your project.
Probably you will need to modify some directory and/or file name in Dockerfile in order to work.
You can try this. The value of FIRST_ENV_VAR inside docker will be set to the value of FIRST_ENV_VAR_ON_HOST on your host system.
version: '3.6'
services:
app:
image: myRegistry/myProject:tag
restart: always
environment:
- FIRST_ENV_VAR=$FIRST_ENV_VAR_ON_HOST
- SECOND_ENV_VAR=$SECOND_ENV_VAR_ON_HOST
ports:
- 8080:8080
As you can see in the docker docs docker-compose reference envs
the defined environment values are always available in the container, not only at build stage.
You can check this by change the CMD to execute the command "env" to display all environments in your container.
If your application is not getting the actual values of the env variables it should be anything else related with your app

Operation of the mkdir command with dockerfile

I cannot create a directory with the mkdir command in a container with dockerfile.
My Dockerfile file is simply ;
FROM php:fpm
WORKDIR /var/www/html
VOLUME ./code:/var/www/html
RUN mkdir -p /var/www/html/foo
In this way I created a simple php: fpm container.
and I wrote to create a directory called foo.
docker build -t phpx .
I have built with the above code.
In my docker-compose file as follows.
version: '3'
services:
web:
container_name: phpx
build : .
ports:
- "80:80"
volumes:
- ./code:/var/www/html
later; run the following code and I entered the container kernel.
docker exec -it phpx /bin/bash
but there is no a directory called foo in / var / www / html.
I wonder where I'm doing wrong.
Can you help me?
The reason is that you are mounting a volume from your host to /var/www/html.
Step by step:
RUN mkdir -p /var/www/html/foo creates the foo directory inside the filesystem of your container.
docker-compose.yml ./code:/var/www/html "hides" the content of /var/www/html in the container filesystem behind the contents of ./code on the host filesystem.
So actually, when you exec into your container you see the contents of the ./code directory on the host when you look at /var/www/html.
Fix: Either you remove the volume from your docker-compose.yml or you create the foo-directory on the host before starting the container.
Additional Remark: In your Dockerfile you declare a volume as VOLUME ./code:/var/www/html. This does not work and you should probably remove it. In a Dockerfile you cannot specify a path on your host.
Quoting from docker:
The host directory is declared at container run-time: The host directory (the mountpoint) is, by its nature, host-dependent. This is to preserve image portability. since a given host directory can’t be guaranteed to be available on all hosts. For this reason, you can’t mount a host directory from within the Dockerfile. The VOLUME instruction does not support specifying a host-dir parameter. You must specify the mountpoint when you create or run the container.
I am able to create a directory inside the 'workdir' for docker as follows:
Dockerfile content
COPY src/ /app
COPY logging.conf /app
COPY start.sh /app/
COPY Pipfile /app/
COPY Pipfile.lock /app/
COPY .env /app/
RUN mkdir -p /app/logs
COPY logs/some_log.log /app/logs/
WORKDIR /app
I have not mentioned the volume parameter in my 'docker-compose.yaml' file
So here is what I suggest: Remove the volume parameter from the 'Dockerfile' as correctly pointed by the Fabian Braun.
FROM php:fpm
RUN mkdir -p /var/www/html/foo
WORKDIR /var/www/html
And remove the volume parameter from the docker-compose file. It will work. Additionally, I would like to know how you tested of there is a directory named 'foo'.
Docker-compose file content
version: '3'
services:
web:
build:
context: .
dockerfile: Dockerfile # The name of your docker file
container_name: phpx
ports:
- "80:80"
You can use the SHELL instruction of Dockerfile.
ENV HOME /usr/local
SHELL ["/bin/sh", "-c"]
RUN mkdir $HOME/logs

How to make a docker compose file for an existing image?

What I am trying to do is use a Docker image I found online timwiconsulting/ionic-v1.3, and run my ionic project within Docker. I want to mount my ionic project in Docker and forward my ports so I can run the emulator in a browser.
I want to ask how do I create a docker-compose.yml file for an existing container?
I found a Docker image timwiconsulting/ionic-v1.3 that I want to run, which has the correct version of the tools that I want.
Now I want to create a compose file to forward the ports to my computer, and mount the project files. I create this docker-compose.yml file:
version: '3'
services:
web:
build: .
ports:
- "8100:8100"
- "35729:35729"
volumes:
- /Users/leetcat/project/:/project
But every time I try to do docker-compose up I get the error:
~/user: docker-compose up
Building web
Step 1/6 : FROM timwiconsulting:ionic-v1.3
ERROR: Service 'web' failed to build: pull access denied for timwiconsulting, repository does not exist or may require 'docker login
I am doing something wrong. I think I want to be creating a docker-compose.yml file for the container timwiconsulting/ionic-v1.3. Feel free to tell me I am totally off the mark with what docker is.
Here is my Dockerfile:
# Use an official Python runtime as a parent image
FROM timwiconsulting:ionic-v1.3
# Set the working directory to /app
WORKDIR /project
# Copy the current directory contents into the container at /app
ADD . /project
# Install any needed packages specified in requirements.txt
# RUN pip install --trusted-host pypi.python.org -r requirements.txt
# Make port 80 available to the world outside this container
EXPOSE 8100
EXPOSE 35729
# Define environment variable
ENV NAME World
# Run app.py when the container launches
# CMD ["python", "app.py"]
# docker exec -it <container_hash> /bin/bash/

create docker-compose file from Dockerfile

I have this simple Dockerfile:
FROM node:boron
# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
# Install app dependencies
COPY package.json /usr/src/app/
RUN npm install
# Bundle app source
COPY . /usr/src/app
EXPOSE 8080
CMD [ "npm", "start" ]
I would like to use docker-compose so that I can simply say docker-compose up or docker-compose down.
I am struggling to find a simple docker-compose example of how I would use docker-compose, all I can find are examples like this which cover more ground than I need.
How could I create a simple docker-compose file from the above?
You write following in docker-compose.yml file to run your docker container using compose:
version: '3'
services:
app:
build: .
ports:
- 8080:8080
Docker compose file is made of multiple services but in your case it is enough to define one service. build option specifies from where to pick up the Dockerfile to build the image and ports will allow port forwarding from the container to you host OS.
To start the service you can use:
docker-compose up
And to stop the service:
docker-compose down
You can find more documentation about the compose file here

Resources