I have a web app in a docker container that connects to a Redis server running in the same docker container. I get around 150ms get and set commands when running this environment in docker (locally and when deployed). When I run the same web app outside of docker, connecting to a Redis server installed on my local machine, I get around 5-10ms timings for most Redis operations, as I should. What on earth could be wrong with my docker container that could cause timings of over 150ms when connecting within the same docker container?
Dockerfile
FROM crystallang/crystal:0.34.0
...
RUN wget http://download.redis.io/redis-stable.tar.gz
RUN tar xvzf redis-stable.tar.gz
WORKDIR /redis-stable
RUN make -j4
RUN cp src/redis-server /usr/local/bin/
RUN cp src/redis-cli /usr/local/bin/
RUN cp utils/redis_init_script /etc/init.d/redis_6379
RUN mkdir -p /var/redis/6379
COPY /redis.conf /etc/redis/6379.conf
RUN update-rc.d redis_6379 defaults
...
EXPOSE 3000
HEALTHCHECK CMD ["/app", "-c", "http://localhost:3000/"]
ENTRYPOINT ["./prod_init.sh"]
prod_init.sh
#!/bin/sh
/etc/init.d/redis_6379 start &
exec [web app startup procedure here]
redis.conf
https://gist.github.com/sam0x17/5af8ca142e9eec692d30057160b45d6b
docker stats
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
06908bd70a00 myapp 0.14% 231MiB / 31.28GiB 0.72% 127kB / 75.9kB 1.11MB / 0B 38
Related
before I start: I have searched this question already and implemented what the "Solutions" were and it did not help (setting host to 0.0.0.0). So, with that out of the way,
Directory structure
|-- osr
| |-- __init__.py
|-- requirements.txt
|-- Dockerfile
|-- docker-compose.yml
Dockerfile:
FROM python:3.7.5-buster
EXPOSE 5000 # i have tried with and without this
ENV INSTALL_PATH /osr
ENV FLASK_APP osr
ENV FLASK_ENV development
RUN mkdir -p $INSTALL_PATH
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
COPY . .
CMD [ "flask", "run", "--host=0.0.0.0"]
docker-compose.yml:
version: '3.8'
services:
web:
build: .
ports:
- '5000:5000'
expose:
- '5000'
volumes:
- .:/osr
__ init __.py
import os
from flask import Flask
def create_app(test_config=None):
app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping(
SECRET_KEY='dev'
)
#app.route('/hello')
def hello():
return 'Hello, World!'
return app
docker-compose build web
docker-compose run web
* Serving Flask app "osr" (lazy loading)
* Environment: development
* Debug mode: on
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 225-441-434
all of the below return "hmm can't reach this page"
http://localhost
http://localhost:5000/hello
http://127.0.0.1:5000/hello
I've even tried going to the containers IP with
docker exec -it 49e677 bash
ip add | grep global
inet 172.21.0.2/16 brd 172.21.255.255 scope global eth0
http://127.21.0.2:5000/hello # nothing
Nothing.
I'm sure the app itself works fine as I can simply run the app directly.
$env:FLASK_APP="osr"
$env:FLASK_ENV="development"
flask run --host=0.0.0.0
And it runs fine
EDIT: UPDATE
I am actually able to get to the container when I run it through simply the Dockerfile... using
docker run -it -p 5000:5000 osr_web # the container built by docker-compose build
With this, I am able to access the endpoint through localhost:5000/hello
So the issue appears to lie in spinning it up through docker-compose run
Does this help at all?
UPDATE 2
I have discovered that when I run docker ps -a I can see that Docker run actually exposes the port, but docker-compose run does not:
Are you sure app works fine itself? I tried to run your python __init__.py file and ended up with an error.
python osr/__init__.py
File "osr/__init__.py", line 11
def hello():
^
IndentationError: unexpected indent
It works after fixing the indentation error.
#app.route('/hello')
def hello():
return 'Hello, World!'
$ docker run -d -p 5000:5000 harik8/osr:latest
76628f86fecb61c0be4a969d3c91c5c575702ad8063b594a6c1c90b498ea25f1
$ curl http://127.0.0.1:5000/hello
Hello, World!
You can't run both docker and docker-compose in port 5000 at the same time. Either run one at a time or change the docker-compose/dockerfile host port.
$ docker ps -a | grep osr
8b885c4a9654 harik8/osr:latest "flask run --host=0.…" 12 seconds ago Up 11 seconds 0.0.0.0:5000->5000/tcp
$ docker ps -a | grep q5
70f38bf11e26 q5_web "flask run --host=0.…" About a minute ago Up 10 seconds 0.0.0.0:5001->5000/tcp
$ docker ps -a | grep q5
f9f6ba999109 q5_web "flask run --host=0.…" 5 minutes ago Up 5 minutes 0.0.0.0:5000->5000/tcp q5_web_1
$ docker ps -a | grep osr
93fb421333e4 harik8/osr:latest "flask run --host=0.…" 18 seconds ago Up 18 seconds 5000/tcp
I found the issue. For reference, I am running these versions:
docker-compose version 1.25.5, build 8a1c60f6
Docker version 19.03.8, build afacb8b
There were a couple issues: First and foremost to get the ports exposed I needed to run one of two options.
docker-compose up web
or
docker-compose run --service-ports web
Simply running docker-compose run web would not expose the ports.
Once this was finished, I was able to access the endpoint. However I started getting another odd error,
flask.cli.NoAppException
flask.cli.NoAppException: Failed to find Flask application or factory in module
"osr". Use "FLASK_APP=osr:name to specify one.
I had not experienced this simply using docker run -it -p 5000:5000 osr_web which was odd. However I noticed I had not set the work directory in the Dockerfile.
I changed the Dockerfile to this:
FROM python:3.7.5-buster
EXPOSE 5000
ENV INSTALL_PATH /osr
ENV FLASK_APP osr
ENV FLASK_ENV development
RUN mkdir -p $INSTALL_PATH
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
# added this line
WORKDIR $INSTALL_PATH
COPY . .
CMD [ "flask", "run", "--host=0.0.0.0"]
I believe you could get away without setting the WORK_DIR if you turn the flask application into a package and install it.
I am having some issues deploying to Cloud Run lately. When I am trying to deploy the below Dockerfile to Cloud Run, it ends up with the error Failed to start and then listen on the port defined by the PORT environment variable.:
FROM phpmyadmin/phpmyadmin:latest
EXPOSE 8080
RUN sed -i 's/80/${PORT}/g' /etc/apache2/sites-available/000-default.conf /etc/apache2/ports.conf
ENTRYPOINT [ "/docker-entrypoint.sh" ]
CMD [ "apache2-foreground" ]
The ENTRYPOINT and CMD were added separately even though the phpmyadmin/phpmyadmin:latest uses this same ENTRYPOINT and CMD to see if that would solve it, though it is not required. The same Docker image when deployed using docker run runs properly and listens on port 8080. Is there something I am doing wrong?
This is the command I use to deploy:
gcloud run deploy phpmyadmin --memory=1Gi --platform=managed \
--allow-unauthenticated --add-cloudsql-instances project_id:us-central1:db-name \
--region=us-central1 --image gcr.io/project_id/phpmyadmin:1.3 \
--update-env-vars PMA_HOST=localhost,PMA_SOCKET="/cloudsql/project_id:us-central1:db-name",PMA_ABSOLUTE_URI=phpmyadmin.domain.com
This is all I can find in the logs. (Have redacted some data):
https://gist.github.com/shanukk27/9dd4b3076c55307bd6e853a76e7a34e0
Cloud Run runtime environment seems to be slightly different than Docker run command. You can't use ENTRYPOINT and CMD in the same time
ENTRYPOINT [ "/docker-entrypoint.sh" ]
CMD [ "apache2-foreground" ]
It works with Docker Run (Why? Docker issue? Docker feature?) and not on Cloud Run (missing feature? bug?).
Use only one of them, for example:
ENTRYPOINT /docker-entrypoint.sh && apache2-foreground
EDIT
A strange remark shared by Shanu is the 2 command works with Wordpress deployment, and doesn't work here.
FROM wordpress:5.3.2-php7.3-apache
EXPOSE 8080
# Copy custom entrypoint from repo
COPY cloud-run-entrypoint.sh /usr/local/bin/
# Change apache listening port and set permission for docker entrypoint
RUN sed -i 's/80/${PORT}/g' /etc/apache2/sites-available/000-default.conf /etc/apache2/ports.conf && \
chmod +x /usr/local/bin/cloud-run-entrypoint.sh
# Wordpress conf
COPY wordpress/. /var/www/html/
# Custom entrypoint
ENTRYPOINT ["cloud-run-entrypoint.sh","docker-entrypoint.sh"]
# Start apache when docker container starts
CMD ["apache2-foreground"]
The problem is solved here, but the reason is not clear
Note to Googler (Steren? Ahmet?): Can you share more details on this behavior?
I can't access my Vue app on localhost:8080 anymore after Dockerizing the app.
I have a Dockerfile with the following contents:
# Base the image off of the NodeJS image
FROM node
# Set the working directory to be the HOME directory
WORKDIR /root
# Install NPM dependencies early in the build process
COPY ./package.json /root
COPY ./package-lock.json /root
RUN npm install
# Specify what port will be available - necessary for VPC network
EXPOSE 8080
# Copy our application files to the image
COPY ./.browserslistrc /root
COPY ./.eslintrc.js /root
COPY ./.env /root
COPY ./babel.config.js /root
COPY ./README.md /root
COPY ./vue.config.js /root
COPY ./public /root/public
COPY ./src /root/src
# Start the container running our Node app
CMD ["npm", "run", "serve"]
(Before Dockerizing, npm run serve allowed me to access the Vue app through my web browser.)
Then I run the PS command docker build:
PS C:\Users\User\mealSocial-dev> docker build -t finalvue app
Sending build context to Docker daemon 126.8MB
Step 1/15 : FROM node
---> 448d0873ea84
[...]
Step 15/15 : CMD ["npm", "run", "serve", "--port", "\"8080\""]
---> Running in c4840f98e5dc
Removing intermediate container c4840f98e5dc
---> 904928fa859c
Successfully built 904928fa859c
Successfully tagged finalvue:latest
SECURITY WARNING: You are building a Docker image from Windows against a non-Windows Docker host. All files and directories added to build context will have '-rwxr-xr-x' permissions. It is recommended to double check and reset permissions for sensitive files and directories.
...Then docker run -p 8080:8080:
PS C:\Users\User\mealSocial-dev> docker run -p 8080:8080 finalvue
> meal-app#0.1.0 serve /root
> vue-cli-service serve
INFO Starting development server...
<s> [webpack.Progress] 0% compiling
[...]
DONE Compiled successfully in 8147ms11:39:59 AM
<s> [webpack.Progress] 100%
App running at:
- Local: http://localhost:8080/
It seems you are running Vue CLI inside a container.
Access the dev server via http://localhost:<your container's external mapped port>/
Note that the development build is not optimized.
To create a production build, run npm run build.
Despite it saying It seems you are running Vue CLI inside a container. Access the dev server via http://localhost:<your container's external mapped port>/, I get This page isn’t working. localhost didn’t send any data. ERR_EMPTY_RESPONSE:
I'm EXPOSE-ing the port in the Dockerfile and adding the -p 8080:8080 tag when I run docker run. What am I missing?
from the comment section:
add --host 0.0.0.0 to npm run serve
or
add host: 0.0.0.0 to a config (./vue.config.js)
Based on this guide:
https://shekhargulati.com/2019/01/18/dockerizing-a-vue-js-application/
I have created a sample VueJS app and created a docker image:
docker build -t myapp .
based on the below Dockerfile:
# base image
FROM node:10.15.0
# set working directory
RUN mkdir /usr/src/app
WORKDIR /usr/src/app
# add `/usr/src/app/node_modules/.bin` to $PATH
ENV PATH /usr/src/app/node_modules/.bin:$PATH
# install and cache app dependencies
COPY package.json /usr/src/app/package.json
RUN npm install
RUN npm install -g #vue/cli
# start app
CMD ["npm", "run", "serve"]
Next I run a docker container with:
docker run -it -v ${PWD}:/usr/src/app -v /usr/src/app/node_modules -p 5000:5000 myapp
and get this (successfull) output:
DONE Compiled successfully in 4644ms 4:05:10 PM
No type errors found
No lint errors found
Version: typescript 3.4.3, tslint 5.15.0
Time: 4235ms
App running at:
- Local: http://localhost:8080/
It seems you are running Vue CLI inside a container.
Access the dev server via http://localhost:<your container's external mapped port>/
Note that the development build is not optimized.
To create a production build, run npm run build.
I then try to access the application from my browser on: http://localhost:5000/ but I just get a The connection was reset error.
I have also tried to inspect the port information on the running container with:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
755d2745bce2 myapp "npm run serve" 22 seconds ago Up 18 seconds 0.0.0.0:5000->5000/tcp confident_mirzakhani
$ docker port confident_mirzakhani
5000/tcp -> 0.0.0.0:5000
But that basically confirms the port info I passed to the run command.
Any suggestion on how to access the VueJS application in the container from the browser on my host?
I have been successful till completely dockerizing my webserver application. Now I want to explore more by deploying them directly to a mesos slave through marathon framework.
I can deploy a docker container in to a marathon in two different approaches , either command line or through marathon web UI.
Both worked for me but challenge is when I am trying to deploy my docker image, marathon frequently restarting a job and in mesos UI page I can see many finished job for the same container. Close to 10 tasks per minute. Which is not expected I believe.
My docker file looks like below:
FROM ubuntu:latest
#---------- file Author / Maintainer
MAINTAINER "abc"
#---------- update the repository sources list
RUN apt-get update && apt-get install -y \
apache2 \
curl \
openssl \
php5 \
php5-mcrypt \
unzip
#--------- installing composer
RUN curl -sS https://getcomposer.org/installer | php
RUN mv composer.phar /usr/local/bin/composer
RUN a2enmod rewrite
#--------- modifying the 000default file
COPY ./ /var/www/airavata-php-gateway
WORKDIR /etc/apache2/sites-available/
RUN sed -i 's/<\/VirtualHost>/<Directory "\/var\/www"> \n AllowOverride All \n <\/Directory> \n <\/VirtualHost>/g' 000-default.conf
RUN sed -i 's/DocumentRoot \/var\/www\/html/DocumentRoot \/var\/www/g' 000-default.conf
WORKDIR /etc/php5/mods-available/
RUN sed -i 's/extension=mcrypt.so/extension=\/usr\/lib\/php5\/20121212\/mcrypt.so/g' mcrypt.ini
WORKDIR /var/www/airavata-php-gateway/
RUN php5enmod mcrypt
#--------- making storage folder writable
RUN chmod -R 777 /var/www/airavata-php-gateway/app/storage
#-------- starting command
CMD ["sh", "-c", "sh pga-setup.sh ; service apache2 restart ; /bin/bash"]
#--------- exposing apache to default port
EXPOSE 80
Now I am clueless how to resolve this issue,any guidance will be highly appreciated.
Thanks
Marathon is meant to run long-running tasks. So in your case, if you start a Docker container that does not keep listening on a specific port, meaning it exits successfully or unsuccessfully, Marathon will start it again.
For example, I started a Docker container using the simplest image hello-world. That generated more than 10 processes in Mesos UI in a matter of seconds! This was expected. Code inside Docker container was executing successfully and exiting normally. And since it exited, Marathon made sure that another instance of the app was started immediately.
On the other hand, when I start an nginx container which keeps listening on port 80, it becomes a long running task and a new task (Docker container) is spun up only when the existing container exits (successfully or unsuccessfully).
You probably need to work on the CMD section of your Dockerfile. Does the container in question keep running when started normally? That is, without Marathon - just using plain docker run? If yes, check if it keeps running in detached mode - docker run -d. If it exits, then CMD is the part you need to work on.