I want to create simple Kotlin app that uses PostgresSql and Kotlin Ktor, everything should be embedded in docker container.
So far I managed to run separately PostgresSql and PgAdmin which connected to each other successfully and I created docker-compose.yml file for that that works fine form me. The problem starts when I want to add to it my Kotlin app.
Here is my docker-compose.yml file
version: "3.9"
networks:
m8network:
ipam:
config:
- subnet: 172.20.0.0/24
services:
postgres:
image: postgres
environment:
- "POSTGRES_USER=SomeFancyUser"
- "POSTGRES_PASSWORD=pwd"
- "POSTGRES_DB=MSC8"
ports:
- "5432:5432"
volumes:
# - postgres-data:/var/lib/postgresql/data
- D:\docker\myApp\data:/var/lib/postgresql/data
networks:
m8network:
ipv4_address: 172.20.0.6
pgadmin:
image: dpage/pgadmin4
depends_on:
- postgres
environment:
- "PGADMIN_DEFAULT_EMAIL=SomeFancyUser#domain.com"
- "PGADMIN_DEFAULT_PASSWORD=pwd"
# - "PGADMIN_ENABLE_TLS=False"
ports:
- "5001:80"
networks:
m8network:
app:
build: .
ports:
- "5000:8080"
links:
- postgres
depends_on:
- postgres
restart: on-failure
networks:
m8network:
#volumes:
# postgres-data:
# driver: local
And heres is my app source code.
package com.something.m8
import com.squareup.sqldelight.db.SqlDriver
import com.squareup.sqldelight.sqlite.driver.asJdbcDriver
import com.zaxxer.hikari.HikariConfig
import com.zaxxer.hikari.HikariDataSource
import io.ktor.application.*
import io.ktor.html.*
import io.ktor.http.*
import io.ktor.response.*
import io.ktor.routing.*
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import kotlinx.html.*
import java.io.PrintWriter
import java.util.*
fun HTML.index() {
head {
title("Hello from Ktor!")
}
body {
div {
+"Hello from Ktor"
}
}
}
fun main() {
println("starting app")
val props = Properties()
props.setProperty("dataSourceClassName", "org.postgresql.ds.PGSimpleDataSource")
props.setProperty("dataSource.user", "SomeFancyUser")
props.setProperty("dataSource.password", "pwd")
props.setProperty("dataSource.databaseName", "M8")
props.setProperty("dataSource.portNumber", "5432")
props.setProperty("dataSource.serverName", "172.20.0.6")
props["dataSource.logWriter"] = PrintWriter(System.out)
println("a")
val config = HikariConfig(props)
println("b")
val ds = HikariDataSource(config)
println("c")
val driver: SqlDriver = ds.asJdbcDriver()
println("d")
MSC8.Schema.create(driver)
println("e")
embeddedServer(Netty, port = 8080,
// host = "127.0.0.1"
) {
routing {
get("/") {
call.respondHtml(HttpStatusCode.OK, HTML::index)
}
get("/m8/{code}") {
val code = call.parameters["code"]
println("code $code")
call.respondRedirect("https://google.com")
}
}
}.start(wait = true)
}
And the Dockerfile for app
#FROM openjdk:8
FROM gradle:6.7-jdk8
WORKDIR /var/www/html
RUN mkdir -p ./app/
WORKDIR /var/www/html/app
COPY build.gradle.kts .
COPY gradle.properties .
COPY settings.gradle.kts .
COPY Redirect/src ./Redirect/src
COPY Redirect/build.gradle.kts ./Redirect/build.gradle.kts
COPY gradlew .
COPY gradle ./gradle
EXPOSE 8080
USER root
WORKDIR /var/www/html
RUN pwd
RUN ls
RUN chown -R gradle ./app
USER gradle
WORKDIR /var/www/html/app
RUN ./gradlew run
With this setup I have two problems
First problem:
When I run docker-compose.exe up --build I receive exception HikariPool$PoolInitializationException: Failed to initialize pool: The connection attempt failed. on line val ds = HikariDataSource(config)
I set up static ip for postgres (172.20.0.6) and when I'm using this ip in PGAdmin it works so why my app cannot connect to the postgres?
Second problem:
I tried to test if app is starting properly and everything works fine in most basics. So I commented all source code related to the connection to the DB since that point when I run docker-compose.exe up --build my app displays only letter e from line println("e") and at this point everything seems to be frozen, postgres and PGAdming doesn't startup, and after that container seems to be unresponsive and app doesn't respond on port 5000 or 8080. Is there any way that I can run app so it won't block exectution of other parts?
First problem:
I started using host name instead IP adress so now I'm using postgres instead 172.20.0.6. And the rest of it is connected to second problem
Second problem:
The issue was that I was starting the app during build phase of container.
Instead RUN ./gradlew run I used
RUN gradle build
ENTRYPOINT ["gradle","run"]
Also I noticed that I don't have to use gradle wrapper while I'm using FROM gradle:6.7-jdk8
Now everyting is working fine.
Related
i'm using Docker-Desktop on Windows and i'm trying to get running 3 containers inside docker-desktop.
After few research and test, i get the 3 container running [WEB - API - DB], everything seems to compile/run without issue in the logs but i'can't access my web container from outside.
Here's my dockerfile and docker-compose, what did i miss or get wrong ?
[WEB] dockerfile
FROM node:16.17.0-bullseye-slim
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
#EXPOSE 4200 (the issue is the same with or without this line)
CMD ["npm", "run", "start"]
[API] dockerfile
FROM openjdk:17.0.1-jdk-slim
WORKDIR /app
COPY ./target/test-0.0.1-SNAPSHOT.jar /app
#EXPOSE 2022 (the issue is the same with or without this line)
CMD ["java", "-jar", "test-0.0.1-SNAPSHOT.jar"]
Docker-compose file
version: "3.8"
services:
### FRONTEND ###
web:
container_name: wallet-web
restart: always
build: ./frontend
ports:
- "80:4200"
depends_on:
- "api"
networks:
customnetwork:
ipv4_address: 172.20.0.12
#networks:
# - "api"
# - "web"
### BACKEND ###
api:
container_name: wallet-api
restart: always
build: ./backend
ports:
- "2022:2022"
depends_on:
- "db"
networks:
customnetwork:
ipv4_address: 172.20.0.11
#networks:
# - "api"
# - "web"
### DATABASE ###
db:
container_name: wallet-db
restart: always
image: postgres
ports:
- "5432:5432"
environment:
- POSTGRES_PASSWORD=postgres
- POSTGRES_USER=postgres
- POSTGRES_DB=postgres
networks:
customnetwork:
ipv4_address: 172.20.0.10
#networks:
# - "api"
# - "web"
networks:
customnetwork:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
gateway: 172.20.0.1
# api:
# web:
Listening on:
enter image description here
I found several issue similar to mine but the solution didn't worked for me.
If i understand you are trying to access on port 80. To do that, you have to map your container port 4200 to 80 in yaml file 80:4200 instead of 4200:4200.
https://docs.docker.com/config/containers/container-networking/
Have you looked in the browsers development console, if there comes any error. Your docker-compose seems not to have any issue.
How ever lets try to debug it:
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6245eaffd67e nginx "/docker-entrypoint.…" About an hour ago Up About an hour 0.0.0.0:4200->80/tcp test-api-1
copy the container id then execute:
docker exec -it 6245eaffd67e bin/bash
Now you are inside the container. Instead of the id you can use also the containers name.
curl http://localhost:80
Note: in my case here i just create a container from an nginx image.
In your case use the port where your app is running. Control it in your code if you arent sure. A lot of Javascript-frameworks start default on 3000.
If you get an error: curl command not found, install it in your image:
FROM node:16.17.0-bullseye-slim
USER root # to install dependencies you need sudo permissions su we tell the image that it is root
RUN apt update -y && apt install curl -y
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
#EXPOSE 4200 (the issue is the same with or without this line)
USER node # we dont want to execute the image as root so we put user node (this user is defined in the node:16.17.0-bullseye-slim image)
CMD ["npm", "run", "start"]
Now the curl should work (if it doesnt already).
The same should work from your host.
Here is an important thing:
The localhost, always refers to the fisical computer, or the container itselfs where you are refering. Every container and your PC have localhost and they are not the same.
In the docker-compose you just map the port host/container, so your PC (host) where docker is running can access the docker network from the host on the host port you defined, inside the port of the container.
If you cant still access from your host, try to change the host ports 2022, 4200 ecc. Could be possible that something conflicts on your Windows machine.
It happens sometimes that the docker networks can create some conflicts.
Execute a docker-compose down, so it should be delete and recreated.
Still not working?
Reset docker-desktop to factory settings, control if you have last version (this is always better).
If all this doesnt help, let me know so we can debugg further.
For the sake of clarity i post you here the docker-compose which i used to check. I just used nginx to test the ports as i dont have your images.
version: "3.8"
services:
### FRONTEND ###
web:
restart: always
image: nginx
ports:
- "4200:80"
depends_on:
- "api"
networks:
- "web"
### BACKEND ###
api:
restart: always
image: nginx
ports:
- "2022:80"
depends_on:
- "db"
networks:
- "api"
- "web"
### DATABASE ###
db:
restart: always
image: postgres
ports:
- "5432:5432"
environment:
- POSTGRES_PASSWORD=postgres
- POSTGRES_USER=postgres
- POSTGRES_DB=postgres
networks:
- "api"
networks:
api:
web:
```
Update:
You can log what happens in the conatiner like so:
```
docker logs containerid/name
```
If you are using Visualcode there is excellent extension for docker build also by Microsoft:
Just search docker in the extensions. Has something like 20.000.000 downloads and can help you a lot debugging containers ecc. After installing it you see the dockericon on the left toolbar.
If you can see directly the errors that occurs in the logs, maybe you can post them partially. So it would be possible to understand. Please tell also something about your Frontendapp architecture, (react-app, angular). There are some frameworks that need to be startet on 0.0.0.0 instead of 127.0.0.1 or they dont work.
I am trying to learn to deploy apps using docker. I have a flask app I am trying to deploy. Each time I run docker-compose up, the output doesn't show any errors but the app won't load in the browser. I make use of flask-sqlalchemy to connect to a mysql database. The contents of my docker-compose file are as follows:
version: "3.7"
services:
db:
image: mysql:5.7
ports:
- "32000:3306"
environment:
MYSQL_HOST: db
MYSQL_USER: root
MYSQL_ROOT_PASSWORD: data_scientist
volumes:
- ./db/route_client.sql:/docker-entrypoint-initdb.d/route_client.sql:ro
app:
build: C:\abdul_files\flask_apps\leaflet\control_search
links:
- db
ports:
- "5001:5000"
depends_on:
- db
The contents of my Dockerfile are as follows:
# Use an official Python runtime as an image
FROM python:2.7.9
# The EXPOSE instruction indicates the ports on which a container
# will listen for connections
# Since Flask apps listen to port 5000 by default, we expose it
EXPOSE 5000
# Sets the working directory for following COPY and CMD instructions
# Notice we haven’t created a directory by this name - this instruction
# creates a directory with this name if it doesn’t exist
WORKDIR /control_search
# Install any needed packages specified in requirements.txt
COPY requirements.txt /control_search
RUN pip install -r requirements.txt
# Run app.py when the container launches
COPY . /control_search
CMD python control_search.py
The contents of my config file where I have my sqlalchemy database uri are as follows:
import os
class Config(object):
SQLALCHEMY_DATABASE_URI = 'mysql://root:data_scientist#db/route_client'
SECRET_KEY = os.urandom(32)
SESSION_TYPE = 'filesystem'
As I said earlier, the docker-compose up command executes without errors but the app won't load in the browser. Any pointers to what I am doing wrong will be greatly appreciated.
I have a docker-compose file as seen below. The app and the flask are separate containers. I cannot connect to "python" container although both are on the same network. However, if I expose the port 5000 to the outside via port (e.g. - port: "9000:5000") then it is accessible. However, I only want "app" to access the "python" internally and not from outside of host.
Isn't this possible?
version: '3'
services:
python:
build:
context: ./docker/python
image: python:3.6.12
volumes:
- IQData:/NMIQV2/Data
- IQCode:/NMIQV2/Code
- IQAnalysis:/NMIQV2/Analysis
networks:
- base-network app:
build:
context: .
ports:
- "8080:80"
- "5000:5000"
networks:
- base-network
links:
- redis
- mongo
- python
depends_on:
- redis
- mongo
- python networks:
base-network:
driver: bridge
python container Docker File:
FROM python:3.6.12 EXPOSE 5000
EXPOSE 5000
# set the working directory in the container
WORKDIR /NMIQV2/Code
# copy the content of the local src directory to the working directory
COPY src/ .
# copy the dependencies file to the working directory
COPY requirements.txt .
# install dependencies
RUN pip install -r requirements.txt
server.py
from flask import Flask
server = Flask(__name__)
#server.route("/")
def hello():
return "Hello World!"
if __name__ == "__main__":
server.run(host='0.0.0.0', port=5000)
I am running all of these operations on a remove server that is a
VM running Ubuntu 16.04.5 x64.
My Go project's Dockerfile looks like:
FROM golang:latest
ADD . $GOPATH/src/example.com/myapp
WORKDIR $GOPATH/src/example.com/myapp
RUN go build
#EXPOSE 80
#ENTRYPOINT $GOPATH/src/example.com/myapp/myapp
ENTRYPOINT ./myapp
#CMD ["./myapp"]
When I run the docker container using docker-compose up -d, the Go application exits and I see this in the docker logs:
myapp_1 | /bin/sh: 1: ./myapp: Exec format error docker_myapp_1
exited with code 2
If I locate the image using docker images and run the image like:
docker run -it 75d4a95ef5ec
I can see that my golang applications runs just fine:
viper environment is: development HTTP server listening on address:
":3005"
When I googled for this error some people suggested compiling with some special flags but I am running this container on the same Ubuntu host so I am really confused why this isn't working using docker.
My docker-compose.yml looks like:
version: "3"
services:
openresty:
build: ./openresty
ports:
- "80:80"
- "443:443"
depends_on:
- myapp
env_file:
- '.env'
restart: always
myapp:
build: ../myapp
volumes:
- /home/deploy/apps/myapp:/go/src/example.com/myapp
ports:
- "3005:3005"
depends_on:
- db
- redis
- memcached
env_file:
- '.env'
redis:
image: redis:alpine
ports:
- "6379:6379"
volumes:
- "/home/deploy/v/redis:/data"
restart: always
memcached:
image: memcached
ports:
- "11211:11211"
restart: always
db:
image: postgres:9.4
volumes:
- "/home/deploy/v/pgdata:/var/lib/postgresql/data"
restart: always
Your docker-compose.yml file says:
volumes:
- /home/deploy/apps/myapp:/go/src/example.com/myapp
which means your host system's source directory is mounted over, and hides, everything that the Dockerfile builds. ./myapp is the host's copy of the myapp executable and if something is different (maybe you have a MacOS or Windows host) that will cause this error.
This is a popular setup for interpreted languages where developers want to run their application without running a normal test-build-deploy sequence, but it doesn't really make sense for a compiled language like Go where you don't have a choice. I'd delete this block entirely.
The Go container stops running because of this:
WORKDIR $GOPATH/src/example.com/myapp
RUN go build
#EXPOSE 80
#ENTRYPOINT $GOPATH/src/example.com/myapp/myapp
ENTRYPOINT ./myapp
You are switching directories to $GOPATH/src/example.com/myapp where you build your app, however, your entry point is pointing to the wrong location.
To solve this, you either copy the app into the root directory and keep the same ENTRYPOINT command or you copy the application to a different location and pass the full path such as:
ENTRYPOINT /my/go/app/location
I am trying to run a simple flask app in debug mode using docker-compose. I have created my Dockerfile as follows:
FROM jazzdd/alpine-flask
EXPOSE 80
My docker-compose file looks like this:
version: '2'
networks:
test_network:
driver: bridge
services:
db:
networks:
- test_network
image: postgres:9.5.3
env_file:
- docker.env
expose:
- 5432
app:
networks:
- test_network
build: .
env_file:
- docker.env
expose:
- 80
ports:
- 80:80
volumes:
- ./app/:/app
command: -d
My docker.env just has password to postgres database. I created a simple python file as follows:
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world():
return "Hello, World"
if __name__ == '__main__':
app.run(debug=True,host='0.0.0.0')
Now to run the app, I am using docker-compose up -d --build command. I would assume that after the app starts on the server, when I make any change to app.py file, it will be reflected on the webpage without me having to restart the containers. I'm not seeing the expected behavior. I tried setting my local env variable FLASK_DEBUG=1 but not sure if that would help. Am I missing something?
I also referenced this page but didn't see anything useful.
A sample (simplifed) runthru demostrating file edits with no need for container restarts outlined below for your reference.
app.py
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world():
return "Hello, World"
if __name__ == '__main__':
app.run(debug=True,host='0.0.0.0',port=80)
You will need to specify the port for the flask development server in order to match the exposed container port of 80.
screenshot can be viewed here
Summary of Steps in screenshot (MAC OS X):
starting with Empty directory
Create app.py
docker run
curl localhost (this will display Hello, World)
edit app.py
curl localhost (this should display the new edits)
in my case I had a conflict with gevent. here's the workaround:
import os
if not (os.environ.get('FLASK_DEBUG') == 1):
from gevent import monkey
monkey.patch_all()