I was training on writing integration tests on a simple app and I had some of the working. After some errors I terminated the yarn command running the tests in watch mode and when restarting the same command I got the error in the object:
Error: P1017: Server has closed the connection
I am using prisma, nestjs and mySql as a database, containerized in docker.
I used a code from a tutorial as a base and that one works (it is identical to the following one except for the ports, since the tutorial is using postgres)
This it the docker-compose file
version: '3.8'
services:
dev-db:
image: mysql:5.7
#platform: linux/amd64
ports:
- 3308:3306
environment:
MYSQL_ROOT_PASSWORD: 123
MYSQL_DB: dbfornest
test-db:
image: mysql:5.7
#platform: linux/amd64
ports:
- 3305:3306
environment:
MYSQL_ROOT_PASSWORD: 123
MYSQL_DB: dbfornest
These are the scripts in the json file
"db:restart": "docker compose down && docker compose up -d && sleep 1",
"pretest:int": "yarn db:restart && dotenv -e .env.test -- prisma migrate reset --force",
"test:int": "dotenv -e .env.test -- jest -i --no-cache --watch --config jest-int.json"
this is the .env file
DATABASE_URL=mysql://root:123#localhost:3308/dbfornest
this is the .env.test file
DATABASE_URL=mysql://root:123#localhost:3305/dbfornest
the error was in the docker-compose file. The correct way of naming the database for mySQL is MYSQL_DATABASE
Related
I don't know how unique my problem is but I see similar issues throughout the web but I have the scenario that doesn't match any of the problems I've seen.
I have a pretty standard Express app that uses SequelizeJS and MySQL 8. Sequlize has migration which I run using entrypoint.sh that runs sequelize migration command.
# Run migrations
npx sequelize-cli db:migrate
# Preload initial data
npx sequelize-cli db:seed:all
When I run docker compose command the project builds without any issues and sequelize migration and seeds runs. Database connection from sequelize command line works perfectly!
But when I load my homepage the SQL query from the application throws error. The error itself is quite common
{
code: 'ER_NOT_SUPPORTED_AUTH_MODE',
errno: 1251,
sqlMessage: 'Client does not support authentication protocol requested by server; consider upgrading MySQL client',
sqlState: '08004',
fatal: true
}
I have seen this error while mysql 8 and the package mysql used together with sequlizejs. The common solution is to use mysql2 which I am using in my project. I've also tried to run command --default-authentication-plugin=mysql_native_password inside mysql container which didn't help.
Docker Compose
version: '3.9'
services:
linkfy-dashboard:
container_name: linkfy-dashboard
restart: always
depends_on:
- linkfy-mysql
build:
context: .
dockerfile: Dockerfile.dev
ports:
- '10200:3000'
environment:
APP_NAME: Linkfy
DB_HOST: linkfy-mysql
DB_USER: linkfy
DB_PASS: password
DB_NAME: linkfy
COOKIE_SECRET: secret
NONCE_SECRET: secret
COOKIE_SECURE: 'false'
volumes:
- /app/node_modules
- .:/app
networks:
- linkfy
linkfy-mysql:
container_name: linkfy-mysql
command: --default-authentication-plugin=mysql_native_password
restart: always
image: mysql:8
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: linkfy
MYSQL_USER: linkfy
MYSQL_PASSWORD: password
volumes:
- database:/var/lib/mysql
networks:
- linkfy
adminer:
image: adminer
restart: always
ports:
- 10210:8080
networks:
- linkfy
networks:
linkfy:
name: linkfy
volumes:
database:
Dockerfile
FROM node:14.17-alpine
# source directory
WORKDIR /app
# global dependancy
RUN yarn global add sequelize-cli nodemon
# dependency file (package.json and package-lock.json)
COPY package.json .
RUN apk add --update python2 make g++ && rm -rf /var/cache/apk/*
RUN yarn install
# copy the sources
COPY . .
# listener
EXPOSE 3000
ENTRYPOINT ["./entrypoint.sh"]
# command to run
CMD [ "npm", "run", "dev" ]
I need some direction how to troubleshoot this.
I have a problem with connecting Api with MySQL database running in containers. I have Dockerfile for Golang Api:
FROM golang:latest
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
WORKDIR /app/bin
EXPOSE 8080
RUN go run ./../cmd/web/
I usually connect with database in the application using database/sql:
dsn = "user1:pass#tcp(wpmysql:3306)/wp?parseTime=true"
db, err := sql.Open("mysql", dsn)
My docker-compose.yml:
version: '3'
services:
db:
image: mysql:5.7
container_name: ${MYSQL_CONTAINER_NAME}
ports:
- 3306:3306
command: --init-file /usr/src/app/init.sql
volumes:
- ./init.sql:/usr/src/app/init.sql
environment:
- MYSQL_USER=${MYSQL_USER}
- MYSQL_PASSWORD=${MYSQL_PASS}
- MYSQL_DATABASE=${MYSQL_DB}
- MYSQL_ROOT_PASSWORD=${DB_PASSWORD}
networks:
- fullstack
web:
container_name: wpapi
build: .
ports:
- 8080:8080
restart: on-failure
volumes:
- .:/usr/src/app/
depends_on:
- db
networks:
- fullstack
networks:
fullstack:
driver: bridge
In the same directory as docker-compose.yml is file .env:
DB_PASSWORD=pass
MYSQL_PORT=3306
MYSQL_USER=user1
MYSQL_PASS=pass
MYSQL_DB=wp
MYSQL_CONTAINER_NAME=wpmysql
After call commends:
$ docker-compose up -d db
$ docker-compose build web
I get error ERROR main.go:46: dial tcp: lookup wpmysql on 37.8.214.2:53: no such host. List of containers looks like:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9fbaf67df5bf 2778fcda2046 "/bin/sh -c 'go run …" 14 seconds ago Up 13 seconds 8080/tcp mystifying_shannon
7f6c76cc9c4f mysql:5.7 "docker-entrypoint.s…" 40 minutes ago Up About a minute 0.0.0.0:3306->3306/tcp, 33060/tcp wpmysql
Moreover when I try to connect in application by dsn = "user1:pass#tcp(localhost:3306)/wp?parseTime=true" or dsn = "root:pass#tcp(localhost:3306)/wp?parseTime=true" I get another error:
dial tcp 127.0.0.1:3306: connect: connection refused although I can go into container (docker exec -it wpmysql bash -l) and sign in with root and user1 credentials
In your docker file you have:
RUN go run ./../cmd/web/
This will attempt to build AND run your executable during the build process. The network fullstack is not available at this time. I think you probably meant to use:
CMD go run ../cmd/web/
This will set the default command run when you start (i.e. docker-compose up) the container to go run ../cmd/web/. Even better would be:
RUN go build ../cmd/web/
CMD ../cmd/web/web
This will build your application as part of the process of building the container and then set the executable produced as the default command. The benefit of doing this is that compile errors become apparent when you build the image (and it means the application is not built every time you start the container).
I setup a django project in docker container and every thing is working as expected, except I don't find the project database in mysql image.
Dockerfile
FROM python:3
RUN mkdir /django-website
WORKDIR /django-website
COPY . /django-website
RUN pip install -r requirements.txt
docker-compose.yml
version: '3'
services:
db:
image: mysql:5.7
restart: always
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=mywebsite
- MYSQL_USER=root
- MYSQL_PASSWORD=root
ports:
- '33060:3306'
volumes:
- /var/lib/mysql
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/django-website
ports:
- '8000:8000'
links:
- db
settings.py
DATABASES = {
'default': {
'ENGINE': "django.db.backends.mysql",
'NAME': "mywebsite",
'USER': "root",
'PASSWORD': "root",
'HOST': 'db',
'PORT': '3306',
}
}
I ran migrate and it worked:
docker-compose run web python manage.py migrate
I createdsuperuser:
docker-compose run web python manage.py createsuperuser
The development server is working docker-compose up and the site is working as expected, the issue when I navigate in mysql image I don't find my project related database which is mywebsite .
can you please tell me what is missing? if the database is not created, where has the migration been applied?
Thanks in advance.
I'm not sure what you mean by "I logged in mysql image shell but didn't find mywebsite database"
You are migrated the DB successfully, which means, the DB connections are valid and working.
In your docker-compose.yml file, the port mapping done like this, '33060:3306', which means the db's port 3306 is mapped to host machine's port 33060. So, this may be the issue (it's not an issue, kind of typo)
How to check the DB contents?
METHOD-1: check through django-shell of web container
1. run docker-compose up
2. open a new terminal in the same path and run docker ps
you'll get something like below
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
795093357f78 django_1_11_web "python manage.py ru…" 34 minutes ago Up 11 minutes 0.0.0.0:8000->8000/tcp django_1_11_web_1
4ae48f291e34 mysql:5.7 "docker-entrypoint.s…" 34 minutes ago Up 12 minutes 0.0.0.0:33060->3306/tcp django_1_11_db_1
3.Get into the web container by docker exec -it 795093357f78 bash command, where 795093357f78 is the respective container id
4. now you're inside the container. Then, run the command python manage.py dbshell. Now you will be in MYSQL shell of mywebsite (Screenshot)
5. run the command show tables;. It will display all the tables inside the mywebsite DB
METHOD-2: check through db container
1. repeat the steps 1 and 2 in above section
2. get into db container by docker exec -it 4ae48f291e34 bash
3. Now you'll be in bash terminal of MYSQL. Run the following commmand mysql -u root -p and enter the password when prompt
4. now you're in MYSQL server. run the command, show databases;. This will show all the databases in the server.
Have you tried defining the database image in the dockerfile? The following link is somewhat related to your problem:
https://medium.com/#lvthillo/customize-your-mysql-database-in-docker-723ffd59d8fb
I supposed that ports value of host container should be 3306 not 33060.
Use docker-compose.yml with value 3306 :
version: '3'
services:
db:
image: mysql:5.7
restart: always
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=mywebsite
- MYSQL_USER=root
- MYSQL_PASSWORD=root
ports:
- '3306:3306'
volumes:
- /var/lib/mysql
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/django-website
ports:
- '8000:8000'
links:
- db
Hope this works!
You should change the compose specification to version '2'. Take down the container and bring it back up with docker-compose up -d. Or if you intend to stay with version 3, you can instead use the following specification for database environment parameters
```
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: mywebsite
MYSQL_USER: root
MYSQL_PASSWORD: root
```
When you have problems with containers not coming up, docker logs <container-name> --tail 25 -f can give you a lot of information about the cause.
I have my app running on container. I have mysql server started and having trouble to connect my app with mysql server. This is the screenshot of the error
my docker-compose.yml file:
version: '3'
services:
db:
image: mysql
environment:
- MYSQL_ROOT_PASSWORD=new_password
- MYSQL_USER=composetest
- MYSQL_PASSWORD=new_password
- MYSQL_DATABASE=sample_db
- MYSQL_HOST=localhost
web:
build: .
command: bash -c "python check_db.py --service-name mysql --ip db --port 3306 &&
python manage.py migrate &&
python manage.py runserver 0.0.0.0:8000"
volumes:
- .:/code
ports:
- "8000:8000"
You forgot to link the web container to the db container.
Add the following to the web configuration and it should be all:
links:
- db
I would love to write my docker-compose as bellow.
No need to set host and should link the service with depends_on
version: '3'
services:
db:
image: mysql
environment:
- MYSQL_ROOT_PASSWORD=new_password
- MYSQL_USER=composetest
- MYSQL_PASSWORD=new_password
- MYSQL_DATABASE=sample_db
web:
build: .
volumes:
- .:/code
ports:
- "8000:8000"
depends_on:
- db
I have removed the commands from the docker-compose which you can add to the bash script and add to run it at entrypoint. The script will look something like bellow. I am doing cd to go the respective directory where the applications is installed.
run.sh
#!/bin/sh
#getting into the directory where the command should run.
cd /app
python check_db.py --service-name mysql --ip db --port 3306
python manage.py migrate
python manage.py runserver 0.0.0.0:8000
In the database setting part where you set the hostname put the
service name in your case its db .
These is in overall what I do in laravel app deploy must be similar
in your case too
I am trying set up a Django development environment using docker. Though I can connect to the mysql on host machine. But the web container failed to connect to mysql container with following error:
django.db.utils.OperationalError: (2003, "Can't connect to MySQL server on 'db' (111)")
Below are the docker configurations and django configuration:
---------docker-compose.yml---------
version: '2'
services:
web:
build: .
volumes:
- ".:/code/current"
ports:
- "8000:8000"
depends_on:
- db
- redis
links:
- db
- redis
command: ./manage.py runserver 0.0.0.0:8000
db:
image: mysql:5.7
volumes:
- "./.data/db:/var/lib/mysql"
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=goat_db
restart: always
ports:
- "3306:3306"
redis:
restart: always
image: redis:latest
ports:
- "6379:6379"
--------------Dockerfile for web image----------------------
FROM ubuntu:14.04
MAINTAINER Alice
RUN apt-get update
RUN apt-get install -y tar git curl wget emacs build-essential python python-dev python-distribute python-pip libpcre3 libpcre3-dev libmysqlclient-dev python-m2crypto openssl libssl-dev swig freetds-dev python-pymssql nginx subversion
RUN mkdir -p var/www/goat.garenanow.com/current/log
WORKDIR /var/www/goat.garenanow.com/current
ADD requirements.txt /var/www/goat.garenanow.com/current
RUN pip install -r requirements.txt
ADD . /var/www/goat.garenanow.com/current
EXPOSE 8000
------django database configuration---
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'goat_db',
'USER': 'root',
'PASSWORD': 'root',
'HOST': 'db',
'PORT': '3306',
},
If Django tries to connect to your database and MySql is not ready, then you will probably see this error:
django.db.utils.OperationalError: (2003, "Can't connect to MySQL server on 'db' (111)")
The solution for this case is wait for the db server to be ready before run the web server.
How we can do that?
Instead of running the web server directly we create and run a script that it will wait for the db server to be ready. After that the script will run the web server.
docker-compose.yml file (The relevant part is when we overwrite the web:command directive and we run the script instead of run the web server immediately).
version: '3'
services:
db:
restart: always
image: mysql:5.7
container_name: my_db
env_file: env_db
ports:
- "3306:3306"
web:
restart: always
build: ./web
env_file: env_web
command: ./wait_for_db_and_start_server.sh
ports:
- "8000:8000"
depends_on:
- db
Now env_web file (The relevant part is START_CMD variable).
# Add Environment Variables
DB_NAME=docker
DB_USER=docker_user
DB_PASS=docker_password
DB_SERVICE=db
DB_HOST=db
DB_PORT=3306
START_CMD=python manage.py runserver 0.0.0.0:8000
Now, our web Dockerfile (The relevant part is when we add wait_for_db_and_start_server.sh).
FROM python:2.7
ADD wait_for_db_and_start_server.sh .
ADD requirements.txt .
RUN pip install -r requirements.txt
ADD . .
Now wait_for_db_and_start_server.sh file. (Basically, while we cannot connect to our db server on the specified $DB_HOST:$DB_PORT defined in our env_web file, we wait 3 seconds and try again for M_LOOPS times. If we are able to connect to the server, then we run $START_CMD that was defined in our env_web file.)
#!/bin/sh
# Wait for database to get available
M_LOOPS="10"
#wait for mysql
i=0
# http://stackoverflow.com/a/19956266/4848859
while ! curl $DB_HOST:$DB_PORT >/dev/null 2>&1 < /dev/null; do
i=`expr $i + 1`
if [ $i -ge $M_LOOPS ]; then
echo "$(date) - ${DB_HOST}:${DB_PORT} still not reachable, giving up"
exit 1
fi
echo "$(date) - waiting for ${DB_HOST}:${DB_PORT}..."
sleep 3
done
echo "$(date) - ${DB_HOST}:${DB_PORT} Reachable ! - Starting Daemon"
#start the daemon
exec $START_CMD
What's your my.cnf file look like for the db service?
Check the bind-address value and also make sure the grant permissions are correct connecting from the web container.
To test, you could docker exec ... into the web container and try to connect to db host from there.
If you are trying to keep your web container "thin", you may not want to add mysql or postgres client packages, just to check if your db is ready. Some of the popular wait scripts out there have client dependencies.
I just created a simple Python script which makes native calls to see if the DB is functional. In this case I avoid adding valid credentials and just look for an authentication failure message. The example here is for Postgres, but should be easily adapted for MySQL.
wait_for_db.py
import psycopg2.extras
from time import sleep
connect_str = "dbname='postgres' user='nobody' host='db' " + \
"password='foobar'"
while True:
try:
conn = psycopg2.connect(connect_str)
except psycopg2.OperationalError as e:
if "authentication failed" in e.args[0]:
print("Postgres is ready. Launching site.")
break
else:
print("Waiting for postgres...", e.args[0])
sleep(1)
Then set your web container in your dev environment docker-compose.yml so that you have something like
command: bash -c "python wait-for-postgres.py; python manage.py runserver 0.0.0.0:8000"