I'm trying to dockerize my Django app with Docker, but having some trouble connecting with the mysql database since i'm not really experienced with Docker. I have a couple questions:
I have installed mysql and set up the database locally on my computer, do i have to use a mysql image and create a db service in my docker-compose too ? Shouldn't Django connect to mysql normally like it did when it wasn't dockerized ?
If a database is hosted on a server then is mysql installed on that server ? Do i have to use a mysql image to connect to the database ?
Here is my docker-compose.yml:
version: '3.7'
services:
web:
build: ./appchat
command: python appchat/manage.py runserver
ports:
- 8000:8000
- "3306"
network_mode: "host"
And here is the database settings in settings.py:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'USER': 'root',
'PASSWORD': 'root',
'NAME': 'company',
'PORT': '3306',
}
}
Here is the error when i ran docker-compose file:
django.db.utils.OperationalError: (2002, "Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)")
Any help would be appreciated. Thank you.
The application and its database could be running on the same host or different hosts, and in Docker or not.
If the application and its database are running on different hosts, there is nothing unusual about setting this up in Docker. Configure your application with the DNS name of the database server. (I would recommend passing this via environment variables rather than modifying the settings.py file.)
Docker Compose syntax:
environment:
MYSQL_HOST: mysql.example.com
If both are running in the same Docker setup, then Docker provides an internal DNS setup for one to reach the other. In Docker Compose, you can use the services: key as a host name; in plain Docker, you need to manually docker network create but then this trick works.
Plain Docker example:
docker network create app
docker run --net app --name mysql -v $PWD/mysql:/var/lib/mysql/data mysql
docker run --net app --name app -e MYSQL_HOST=mysql myapp
If the database is running on the same host as the application, but outside Docker, and the host is a Mac or Windows system running the Docker Desktop application, then there is a special host.docker.internal hostname
docker run -e MYSQL_HOST=host.docker.internal myapp
For a native-Linux host this shortcut doesn't exist and you need to find out the host's IP address, but then you can treat this like the first case.
Related
I have a Dockerized django application I am running and I am trying to connect it to a mysql server I have that is port forwarded from another docker container. I have done a sanity test already and confirmed that I can connect to my mysql server using mysql workbench on my localhost.
I have my dockerized django application running on network_mode: host so I thought I would be able to simply connect. Sadly I currently error out on docker-compose build with the error django.db.utils.OperationalError: (2002, "Can't connect to MySQL server on '127.0.0.1' (115)")
An accepted resolution to this issue means that my dockerized django application would be able to connect successfully to my mysql server running localhost:29998
SETTINGS.PY (Django Application)
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'mytestdb',
'USER': 'userone',
'PASSWORD': 'password',
'HOST': '127.0.0.1',
'PORT': '29998',
}
}
DJANGO App compose file
version: '3.3'
services:
mydjangoapp:
container_name: mydjangoapp
restart: always
env_file: .env
build: .
volumes:
- ./apps:/apps
- ./core:/core
network_mode: host
Django app dockerfile:
FROM python:3.9
COPY . .
# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
COPY requirements.txt .
# install python dependencies
RUN pip install --upgrade pip
RUN pip install --no-cache-dir -r requirements.txt
# running migrations
RUN python manage.py migrate
# gunicorn
CMD ["gunicorn", "--config", "gunicorn-cfg.py", "core.wsgi"]
Dockerized mysql server (port forwarded to localhost)
version: '3.3'
services:
mysql:
image: mysql:latest
container_name: mymysqlserver
environment:
- MYSQL_DATABASE=mytestdb
- MYSQL_USER=userone
- MYSQL_ROOT_PASSWORD=password
- MYSQL_PASSWORD=password
ports:
- 29998:3306
Do I need to create some sort of docker network / bridge for this to work? (never tried that before).
I have already attempted the following solutions: sol1 (network_mode=host), sol2,
You django app is not working because:
You are running the containers in separated docker-compose files, this causes django container runs in different network than mysql container.
You are trying to connect to localhost (127.0.0.1) inside the django container. This localhost is different to 'localhost' of your computer and is different to the 'localhost' of mysql container. There are 3 different networks. If you want to connect django container with mysql container use the same network (docker network or your computer IP assigned by a router also will works).
You are trying to connect to the exposed port 29998, but this port is exposed from mysql container to your computer. If you are trying to make an internal connection you should use 3306. (If you are using an internal connection, then you don't need to expose the port)
Why not put the two services in same docker compose file and run it from there, like this:
version: '3.3'
services:
mydjangoapp:
container_name: mydjangoapp
restart: always
env_file: .env
build: .
volumes:
- ./apps:/apps
- ./core:/core
network_mode: host
depends_on: mysql
mysql:
image: mysql:latest
container_name: mymysqlserver
environment:
- MYSQL_DATABASE=mytestdb
- MYSQL_USER=userone
- MYSQL_ROOT_PASSWORD=password
- MYSQL_PASSWORD=password
ports:
- 29998:3306
And then update the settings like this:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'mytestdb',
'USER': 'userone',
'PASSWORD': 'password',
'HOST': 'mysql',
'PORT': '3306',
}
}
In that way, the communication between Django and MySQL will be done through docker network, rather than accessing the host machine network.
Apart from that, you need to change the Dockerfile, so that the migration runs after the MySQL server is running. To ensure that, you can add the migration command in the CMD part:
CMD ["sh", "-c", "python manage.py migrate;gunicorn --config gunicorn-cfg.py core.wsgi"]
I dockerized a MySQL database by doing:
docker pull mysql
docker run --name=container_name -p 3307:3307 -e MYSQL_ROOT_PASSWORD=password -d mysql
Now the container <container_name> is the only one I have in Docker, and its network is set by default to "bridge".
Using: docker exec -it container_name mysql -u root -p (then typing the password) I created a brand new database.
I tried reaching that database from my SQL client, using the specified credentials and database url:
server: localhost or container_name, port: 3307, user: root, password: password.
The client doesn't reach the database and I get the following errors:
Connection refused: connect
Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
Can not read response from server. Expected to read 4 bytes, read 0 bytes before connection was unexpectedly lost.
Obviously I get the same error while running my spring boot application (not dockerized yet), but the problem is something in MySQL container since the SQL client isn't working as well.
I've been reading countless questions same as mine, but the solutions that they offer, never work for me.
What's weird is the fact that in the past projects it worked fine.
I'm running Docker on Windows 10 Pro with Hyper-V.
If you're trying to connect from outside of Docker, your docker run -p option is wrong: the second port number always needs to be the standard port number of its service. For MySQL, that second port number needs to be 3306, always. The two port numbers need to match.
docker run -d -p 3307:3306 ... mysql
# ^^^^
# must be the standard port number
If you're trying to connect from inside Docker, then
You must docker network create a network, and docker run --net all involved containers on that network
You must use the other container's name as a host name, not localhost
You must use the standard port number, again 3306; docker run -p options are ignored (and aren't required)
docker network create some-net
docker run -d --net some-net --name database \
-p ... -e ... -v ... \
mysql
docker run -d --net some-net --name application \
-e MYSQL_HOST=database \
-e MYSQL_PORT=3306 \
my/application
If you're running this under Docker Compose, it automatically creates the network for you, and you can use the Compose service name as the host name. You do not need to manually set up networks: or override the container_name:.
version: '3.8'
services:
database:
image: mysql
# ports: [...]
# environment: [...]
# volumes: [...]
application:
build: .
environment:
MYSQL_HOST: database
MYSQL_PORT: '3306'
I have two containers; a node.js server, and a mysql server ...
Both are running fine, I'm trying to connect to the database running in the MySQL container from my node app.
I've created a bridge network:
$ docker network create -d bridge mynetwork
and run both of my containers in this network with:
$ docker run -p 32031:3306 --network mynetwork --name mysql -e MYSQL_ROOT_PASSWORD=abc123 -d mysql:5.7
$ docker run -p 3000:3000 --network mynetwork node-server node index.js
I'm trying to connect with the IP of the mysql container that I found with docker inspect mysql, which is 172.18.0.2 and port 32031.
Where did it go wrong, it's not connecting?
If you connect by IP which you get from docker inspect command. That mean your connection now is 172.18.0.2 and port still 3306
Another way to connect from nodejs (nodejs and mysql in same network). Connect information is:
hostname: mysql // container name
port: 3306
Docker containers connected via a network can communicate internally. Your mysql container is running on port 3306 internally and 32031 externally.
Try connecting via port 3306. It should work.
Ohh, my good luck.
It's working now. I rebuilt the docker image and connected to the database with the IP that I found with inspect mysql container, and with port 32031.
Run docker container same as: $ docker run -p 3000:3000 --network mynetwork node-server node index.js
var pool = mysql.createPool({
connectionLimit : 3,
host : '172.18.0.1',
user : 'root',
port : 32031,
password : 'abc123',
database : 'mydatabase',
charset : 'utf8mb4',
timezone : 'PKT',
timeout : 4000
});
How can I get my Spring App host in docker to access the mysql host on my host mechine(mac) or access a cloud mysql service?
I know if the mysql is another docker container, I can use link in docker. But this situation is not.
version: '3'
I tried the host mode, seems still get the connection refused.
Dockerfile
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ADD ./build/libs/app.jar app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","-Dspring.profiles.active=dev","/app.jar"]
docker-compose.yml
services:
web:
build: .
network_mode: "host"
ports:
- "8080:8080"
PS: 'java -jar -Dspring.profiles.active=dev app.jar' on my host machine works fine.
Can anyone help me?
For latest mac docker, I can use docker.for.mac.localhost as hostname
spring.datasource.url=jdbc:mysql://docker.for.mac.localhost:3306/a_shares...
And some dark magic has been discussed in here Accessing host machine from within docker container
I have a little problem, I can't seem to connect to mysql server community edition running inside a docker container.
I can easily connect to mysql server using the cli by using:
docker exec -it mysqlserver mysql -uroot -p
But if I try to connect with any other database connector, like DataGrip or MySql Workbench, I get an access denied.
But I changed nothing in the configuration files. I set ip as localhost, using the default 3306 port that the container exposed. username I keep as root and the password is exactly the same but it still keeps failing.
Am I missing something, not understanding anything properly?
Some help would be greatly appreciated!
Extra info: I am using MacOS, running the container with Docker for Mac and I am using as of this moment the latest MySql database version.
your container doesn't contain other connectors, try to publish port when you run your container with docker run --name mysql -p 127.0.0.1:3306:3306 .... to link port. And you can connect you to the container with your local cli. Try this doc
Below is the docker-compose.yml that I used to start up a MariaDB instance for testing some queries. MariaDB is API-compatible with MySQL, so no difference.
version: "2"
services:
db:
image: bitnami/mariadb:latest
volumes:
- ./mariadb/data:/bitnami
ports:
- "9001:3306"
environment:
MARIADB_ROOT_PASSWORD: ChangeMeIfYouWant
phpmyadmin:
image: phpmyadmin/phpmyadmin:latest
ports:
- "9010:80"
links:
- db:db
The image is downloaded and the container created and started via docker-compose up. Afterwards, I can easily connect to it using JetBrains DataGrip.
host: localhost
port: 9001
user: root
password: ChangeMeIfYouWant