I am trying to create a virtualised dev environment on Windows using Vagrant and Docker (as are a lot of people). The problem I have is that I cannot connect (or I dont understand how to) from MySQL Workbench running on my Windows laptop to my MySQL DB in a Docker container in Boot2Docker. This is how I visualise the connection:
MySQL Work bench -> 3306 -> Boot2Docker -> 3306 -> Docker -> MySql
However I cannot connect to the DB from MySQLWorkbench. I have tried connection to the Boot2Docker host 10.0.2.15 on 3306 and tcp over ssh using the private key of the Boot2Docker box ".vagrant\machines\dockerhost\virtualbox\id"
What am I doing wrong/what have I misunderstood.
My Vagrantfile:
ENV['VAGRANT_DEFAULT_PROVIDER'] = 'docker'
DOCKER_HOST_NAME = "dockerhost"
DOCKER_HOST_VAGRANTFILE = "./host/Vagrantfile"
Vagrant.configure("2") do |config|
config.vm.network "forwarded_port", guest: 3306, host: 3306
config.vm.define "mysql" do |v|
v.vm.provider "docker" do |d|
d.image = "mysql"
d.env = {
:MYSQL_ROOT_PASSWORD => "root",
:MYSQL_DATABASE => "dockertest",
:MYSQL_USER => "dockertest",
:MYSQL_PASSWORD => "docker"
}
d.ports =["3306:3306"]
d.remains_running = "true"
d.vagrant_machine = "#{DOCKER_HOST_NAME}"
d.vagrant_vagrantfile = "#{DOCKER_HOST_VAGRANTFILE}"
end
end
end
My hosts/Vagrantfile (describing my Boot2docker host) is:
FORWARD_DOCKER_PORTS='true'
Vagrant.configure(2) do |config|
config.vm.provision "docker"
# The following line terminates all ssh connections. Therefore
# Vagrant will be forced to reconnect.
# That's a workaround to have the docker command in the PATH
#Clear any existing ssh connections
####NOTE: ps aux seems to give variable results depending on run -> process number can be ####first #or second causing provision to fail!!!
config.vm.provision "clear-ssh", type: "shell", inline:
"ps aux | grep 'sshd:' | awk '{print $1}' | xargs kill"
# "ps aux | grep 'sshd:' | awk '{print $2}' | xargs kill"
config.vm.define "dockerhost"
config.vm.box = "dduportal/boot2docker"
config.vm.network "forwarded_port",guest: 8080, host: 8080
config.vm.provider "virtualbox" do |vb|
vb.name = "dockerhost"
end
end
Solved. As I suspected the ports were not getting forwarded between the host machine and the docker host. The solution is to move the port forwarding config line:
config.vm.network "forwarded_port", guest: 3306, host: 3306
into the docker host Vagrant file. MySQL Workbench on the Windows host can then connect on localhost:3306.
Related
I want to connect a vagrant vm that installs WordPress and a SQL machine that installs MySQL server and I can't get it done. Anything would help. I basically wanna go in the web1 IP and have the WordPress. Now I get "Error establishing database connection". My Vagrantfile is this one:
( I want to connect web1 and db right now )
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.box = "generic/ubuntu2010"
# Web 1 - 192.168.33.10
config.vm.define "web1" do |web1|
web1.vm.provider "virtualbox" do |vb|
vb.name = "web1"
vb.memory = "1024"
end
web1.vm.hostname = "web1"
web1.vm.network "private_network", ip: "192.168.33.10"
web1.vm.network "forwarded_port", guest: 80, host: 8080
web1.vm.synced_folder "web1_wordpress", "/var/www/html"
web1.vm.provision "shell", inline: <<-SHELL
apt-get update
apt-get install -y apache2 php php-mysql
cd /var/www/html
wget -c http://wordpress.org/latest.zip
unzip latest.zip
mv wordpress/* .
rm index.html
touch wp-config.php
cp wp-config-sample.php wp-config.php
sed -i 's/database_name_here/wordpress/' wp-config.php
sed -i 's/username_here/wpuser/' wp-config.php
sed -i 's/password_here/wppass/' wp-config.php
SHELL
end
# Web 2 -192.168.33.20
config.vm.define "web2" do |web2|
web2.vm.provider "virtualbox" do |vb|
vb.name = "web2"
vb.memory = "1024"
end
web2.vm.hostname = "web2"
web2.vm.network "private_network", ip: "192.168.33.20"
web2.vm.network "forwarded_port", guest: 80, host: 8081
web2.vm.synced_folder "web2_wordpress", "/var/www/html"
web2.vm.provision "shell", inline: <<-SHELL
apt-get update
apt-get install -y apache2 php php-mysql
cd /var/www/html
wget -c http://wordpress.org/latest.zip
unzip latest.zip
mv wordpress/* .
rm index.html
touch wp-config.php
cp wp-config-sample.php wp-config.php
sed -i 's/database_name_here/wordpress/' wp-config.php
sed -i 's/username_here/wpuser/' wp-config.php
sed -i 's/password_here/wppass/' wp-config.php
SHELL
end
# DB - 192.168.33.30
config.vm.define "db" do |db|
db.vm.provider "virtualbox" do |vb|
vb.name = "db"
vb.memory = "1024"
end
db.vm.hostname = "db"
db.vm.network "private_network", ip: "192.168.33.30"
db.vm.provision "shell", inline: <<-SHELL
apt update
apt install -y mysql-server
mysql -u root -e "CREATE DATABASE wordpress;"
mysql -u root -e "CREATE USER 'wpuser'#'localhost' IDENTIFIED BY 'wppass';"
mysql -u root -e "GRANT ALL ON wordpress.* TO 'wpuser'#'localhost';"
SHELL
end
# LB - 192.168.33.40
config.vm.define "lb" do |lb|
lb.vm.provider "virtualbox" do |vb|
vb.name = "lb"
vb.memory = "1024"
end
lb.vm.hostname = "lb"
lb.vm.network "private_network", ip: "192.168.33.40"
lb.vm.network "forwarded_port", guest: 80, host: 80
lb.vm.provision "shell", inline: <<-SHELL
apt update
apt install -y haproxy
SHELL
end
end
Here is my docker-compose file that works fine and I want to reproduce the same results using Vagrant:
version: '3.7'
services:
db:
image: mysql:5.7.36
restart: always
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: test_db
ports:
- "3308:3306"
phpmyadmin:
image: phpmyadmin/phpmyadmin:latest
restart: always
environment:
PMA_HOST: db
PMA_USER: root
PMA_PASSWORD: root
ports:
- "8080:80"
Execute docker-compose up and visit localhost:8080 phpmyadmin works fine.
When I try to the same with vagrant containers are built and they are running, but phpmyadmin is unable to communicate with mysql container.
Here is my Vagrantfile:
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.define "mysql" do |db|
db.vm.network "forwarded_port", guest: 3306, host: 3308
db.vm.hostname = "mysqldb"
db.vm.provider "docker" do |d|
d.image = "mysql:5.7.36"
d.env = {
:MYSQL_ROOT_PASSWORD => "root",
:MYSQL_DATBASE => "test_db"
}
d.remains_running = "true"
end
end
config.vm.define "phpmyadmin" do |pa|
pa.vm.network "forwarded_port", guest: 80, host: 8080
pa.vm.hostname = "phpmyadmin"
pa.vm.provider "docker" do |d|
d.image = "phpmyadmin/phpmyadmin:latest"
d.env = {
:PMA_HOST => "mysqldb",
:PMA_USER => "root",
:PMA_PASSWORD => "root"
}
d.remains_running = "true"
end
end
end
How can I get the phpmyadmin and MySQL working together with vagrant?
I got the solution. I need to define the network at the top level.
# -*- mode: ruby -*-
# vi: set ft=ruby :
# This file works exactly like the docker-compose.yml file.
Vagrant.configure("2") do |config|
# Define the network, using which the containers can communicate
config.vm.network :private_network, type: "dhcp"
config.vm.define "mysql" do |db|
# Without prot forwardign vagrant entwork doesnt work
db.vm.network "forwarded_port", guest: 3306, host: 3306
db.vm.hostname = "mysqldb"
db.vm.provider "docker" do |d|
d.image = "mysql:5.7.36"
d.env = {
:MYSQL_ROOT_PASSWORD => "root",
:MYSQL_DATBASE => "test_db"
}
d.remains_running = "true"
end
end
config.vm.define "phpmyadmin" do |pa|
pa.vm.network "forwarded_port", guest: 80, host: 8080
pa.vm.hostname = "phpmyadmin"
pa.vm.provider "docker" do |d|
d.image = "phpmyadmin/phpmyadmin:latest"
d.env = {
:PMA_HOST => "mysqldb",
:PMA_USER => "root",
:PMA_PASSWORD => "root",
# Without specifying the specific port phpadmin container doesn't work
:PMA_PORT => "3306",
}
d.remains_running = "true"
end
end
end
I still need to solve one more problem - how to define a dependency between vms. Build the VM phpmyadmin only after mysql is up and running.
Unlike docker-compose it is not possible to set a direct dependency in vagrant. But it is possible to do a sequential build by setting the option --no-parallel eg:- vagrant up --no-parallel.
Even though docker-compose has the dependency set, the dependency is only to the extent of waiting for the dependent container to be built but not waiting for the services in the container to be up and running.
Hence even after building sequentially in vagrant, the dependent services failed to connect. It did not matter vagrant or docker-compose. Services with in the containers need to wait for their dependent services to be up.
So I added a delay in the dependent containers in a timed loop, the dependent service will attempt to connect and upon failure will wait for 30 seconds to connect again, after 10 attempts it gives up.
I just new up a laravel project on homestead. I already ssh on my virtual machine, edited the .env file and run "php artisan migrate". it clearly ran with out issue. Now I want to view the database tables created using sequel pro. I can connect with the database but the tables are not there.
Here's my database .env entry:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret
Homestead set up:
ip: "192.168.10.10"
memory: 2048
cpus: 1
provider: virtualbox
authorize: ~/.ssh/id_rsa.pub
keys:
- ~/.ssh/id_rsa
folders:
- map: ~/site
to: /home/vagrant/site
sites:
- map: homestead.test
to: /home/vagrant/site/rm/public
databases:
- homestead
Sequel Pro:
Name: homestead
Host: 127.0.0.1
Username: homestead
Password: secret
Port: 33060
When I connect with Sequel Pro, the homestead database is empty even when refreshed. I should be seeing the just created tables by the "migrate" command but I am not.
I managed to see through what happened. I have not seen any documentation change to Vagrant 2.2.6 but I believe the default ports were changed. I reviewed the installation logs as:
==> -homestead-8: Forwarding ports...
-homestead-8: 80 (guest) => 2201 (host) (adapter 1)
-homestead-8: 443 (guest) => 2202 (host) (adapter 1)
-homestead-8: 3306 (guest) => 2203 (host) (adapter 1) //this is now 2203 from 33060
-homestead-8: 4040 (guest) => 2204 (host) (adapter 1)
-homestead-8: 5432 (guest) => 2205 (host) (adapter 1)
-homestead-8: 8025 (guest) => 2206 (host) (adapter 1)
-homestead-8: 27017 (guest) => 2207 (host) (adapter 1)
-homestead-8: 22 (guest) => 2208 (host) (adapter 1)
I changed port 33060 forwarded from 3306 to the new 2203. it is now working fine.
I'm very new for docker, now I am trying to run django with mariadb in docker through docker-compose, but I always get this error:
I use Docker version 17.09.1-ce, build 19e2cf6, docker-compose version 1.18.0, build 8dd22a9
django.db.utils.OperationalError: (2003, 'Can\'t connect to MySQL
server on \'mariadb55\' (111 "Connection refused")')
I can connect db correctly after run docker-compose up db in local or remote, and I even can run python manage.py runserver 0.0.0.0:6001 correctly in anaconda virtual environment to connect db service in docker by setting parameters of settings.py file like below:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'test',
'USER': 'belter',
# 'HOST': 'mariadb55',
'HOST': '127.0.0.1',
'PORT': '3302',
'PASSWORD': 'belter_2017',
'default-character-set': 'utf8',
'OPTIONS': {
'sql_mode': 'traditional',
}
}
}
This is my docker-compose.yml file
version: '3'
services:
db:
image: mariadb:5.5
restart: always
environment:
- MYSQL_HOST=localhost
- MYSQL_PORT=3306
- MYSQL_ROOT_HOST=%
- MYSQL_DATABASE=test
- MYSQL_USER=belter
- MYSQL_PASSWORD=belter_2017
- MYSQL_ROOT_PASSWORD=123456_abc
volumes:
- /home/belter/mdbdata/mdb55:/var/lib/mysql
ports:
- "3302:3306"
web:
image: onlybelter/django_py35
command: python3 manage.py runserver 0.0.0.0:6001
volumes:
- /mnt/data/www/mysite:/djcode
ports:
- "6001:6001"
depends_on:
- db
links:
- db:mariadb55
I almost tried everything I can find, but still cannot figure it out, any help would be nice!
What I have tried:
Docker compose mysql connection failing
Linking django and mysql containers using docker-compose
Django connection to postgres by docker-compose
Finally, I figured it out!
The key point is, just as #SangminKim said, I need to use 3306 not 3302 in settings.py, and use db as HOST not 127.0.0.1.
So this is my docker-compose.yml file now:
version: '3'
services:
db:
image: mariadb:5.5
restart: always
environment:
- MYSQL_HOST=localhost
- MYSQL_PORT=3306 # cannot change this port to other number
- MYSQL_ROOT_HOST=%
- MYSQL_DATABASE=test
- MYSQL_USER=belter
- MYSQL_PASSWORD=belter_2017
- MYSQL_ROOT_PASSWORD=123456_abc
volumes:
- /home/belter/mdbdata/mdb55:/var/lib/mysql
ports:
- "3302:3306"
web:
image: onlybelter/django_py35
command: python3 manage.py runserver 0.0.0.0:6001
volumes:
- .:/djcode
ports:
- "6001:6001"
depends_on:
- db
So now we can connect this docker-mysql by mysql -h 127.0.0.1 -P 3302 -u root -p in shell directly, but we have to use db and 3306 in django settings.py file:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'test',
'USER': 'belter',
# 'HOST': 'mariadb55',
'HOST': 'db', #<---
'PORT': '3306', #<---
'PASSWORD': 'belter_2017',
'default-character-set': 'utf8',
'OPTIONS': {
'sql_mode': 'traditional',
}
}
}
And we can still check if this port is open, by running extra command in docker-compose.yml file:
...
web:
image: onlybelter/django_py35
command: /bin/sh -c "python check_db.py --service-name mysql --ip db --port 3306"
volumes:
- .:/djcode
...
Here is check_db.py file:
# check_db.py
import socket
import time
import argparse
""" Check if port is open, avoid docker-compose race condition """
parser = argparse.ArgumentParser(description='Check if port is open, avoid\
docker-compose race condition')
parser.add_argument('--service-name', required=True)
parser.add_argument('--ip', required=True)
parser.add_argument('--port', required=True)
args = parser.parse_args()
# Get arguments
service_name = str(args.service_name)
port = int(args.port)
ip = str(args.ip)
# Infinite loop
while True:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
result = sock.connect_ex((ip, port))
if result == 0:
print("{0} port is open! Bye!".format(service_name))
break
else:
print("{0} port is not open! I'll check it soon!".format(service_name))
time.sleep(3)
By the way, this is my Dockerfile for build django-py35:
FROM python:3.5-alpine
MAINTAINER Xin Xiong "xiongxin20008#126.com"
ENV PYTHONUNBUFFERED 1
RUN set -e; \
apk add --no-cache --virtual .build-deps \
gcc \
libc-dev \
linux-headers \
mariadb-dev \
python3-dev \
postgresql-dev \
freetype-dev \
libpng-dev \
g++ \
;
RUN mkdir /djcode
WORKDIR /djcode
ENV REFRESHED_AT 2017-12-25
ADD requirements.txt /djcode/
RUN pip install --no-cache-dir -r /djcode/requirements.txt
RUN pip install uwsgi
ADD . /djcode/ # copy . to /djcode/
EXPOSE 6001
See more details from here: https://github.com/OnlyBelter/django-compose
You should use the container name instead of localhost (or 127.0.0.1) in your settings.py file. Try providing a container name to the db service in the docker-compose.yml file using container_name attribute and replace the host name in the settings.py by the value of the container_name. (Make sure that they are in the same network that docker compose creates for you.)
Build container with this:
docker run --name mysql-latest \
-p 3306:3306 -p 33060:33060 \
-e MYSQL_ROOT_HOST='%' -e MYSQL_ROOT_PASSWORD='strongpassword' \
-d mysql/mysql-server:latest
Make sure MYSQL_ROOT_HOST='%', that means root can connect from any IP.
I downloaded and installed My SQL from http://downloads.mysql.com/archives/mysql-5.0/mysql-5.0.91.tar.gz. The build was successfully and I installed in to a local non-root directory.
However when try to invoke mysql from command line I get the below error -
Linux:>prakash_prasad/bin/mysql-5.0.91/bin 1021> ./mysql
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
Linux:>prakash_prasad/bin/mysql-5.0.91/bin 1022>
Googling around it states modify / create - /etc/my.cnf - but I do not have permissions to create file in /etc. There has to some other fix for the above issue. I greped which MySql files in installation directory has config /tmp/mysql.sock:
Linux:>prakash_prasad/bin/mysql-5.0.91 1018> grep -ir tmp . | grep sock
./include/mysql/mysql_version.h:#define MYSQL_UNIX_ADDR "/tmp/mysql.sock"
./bin/mysqld_safe:safe_mysql_unix_port=${mysql_unix_port:-${MYSQL_UNIX_PORT:-/tmp/mysql.sock}}
./bin/mysql_config:socket='/tmp/mysql.sock'
./bin/mysqld_multi:socket = /tmp/mysql.sock2
./bin/mysqld_multi:socket = /tmp/mysql.sock3
./bin/mysqld_multi:socket = /tmp/mysql.sock4
./bin/mysqld_multi:socket = /tmp/mysql.sock6
./share/mysql/my-small.cnf:socket = /tmp/mysql.sock
./share/mysql/my-small.cnf:socket = /tmp/mysql.sock
./share/mysql/my-medium.cnf:socket = /tmp/mysql.sock
./share/mysql/my-medium.cnf:socket = /tmp/mysql.sock
./share/mysql/my-large.cnf:socket = /tmp/mysql.sock
./share/mysql/my-large.cnf:socket = /tmp/mysql.sock
./share/mysql/my-huge.cnf:socket = /tmp/mysql.sock
./share/mysql/my-huge.cnf:socket = /tmp/mysql.sock
./share/mysql/my-innodb-heavy-4G.cnf:socket = /tmp/mysql.sock
./share/mysql/my-innodb-heavy-4G.cnf:socket = /tmp/mysql.sock
./share/man/man1/mysql-stress-test.pl.1:/tmp/mysql\&.sock\&.
./share/man/man1/mysql-test-run.pl.1:shell> \fB\&.\&./mysql \-S \&./var/tmp/master\&.sock \-h localhost \-u root\fR
./share/man/man1/mysql_config.1: \-\-socket [/tmp/mysql\&.sock]
./share/man/man1/mysqld_multi.1:shell> \fBmysql \-u root \-S /tmp/mysql\&.sock \-p\fR
./share/man/man1/mysqld_multi.1:socket = /tmp/mysql\&.sock2
./share/man/man1/mysqld_multi.1:socket = /tmp/mysql\&.sock3
./share/man/man1/mysqld_multi.1:socket = /tmp/mysql\&.sock4
./share/man/man1/mysqld_multi.1:socket = /tmp/mysql\&.sock6
./share/man/man8/mysqlmanager.8:/tmp/mysqlmanager\&.sock\&. This option has no meaning on Windows\&.
./share/man/man8/mysqlmanager.8:socket=/tmp/manager\&.sock
./share/man/man8/mysqlmanager.8:socket=/tmp/mysql\&.sock
./share/man/man8/mysqlmanager.8:socket = /tmp/mysql\&.sock5
./share/man/man8/mysqlmanager.8:| socket | /tmp/mysql\&.sock3 |
./mysql-test/suite/funcs_1/views/func_view.inc:# ./mysql-test-run.pl --socket=var/tmp/master.sock --start-dirty
./mysql-test/mysql-test-run-shell:LOCAL_SOCKET=/tmp/mysql.sock
./mysql-test/mysql-test-run-shell:MASTER_MYSOCK="$MYSQL_TMP_DIR/master.sock"
./mysql-test/mysql-test-run-shell:SLAVE_MYSOCK="$MYSQL_TMP_DIR/slave.sock"
./mysql-test/mysql-test-run-shell: $MYSQLADMIN --no-defaults -uroot --socket=$MYSQL_TMP_DIR/$ident.sock$3 --connect_timeout=5 --shutdown_timeout=70 shutdown >> $MYSQL_MANAGER_LOG 2>&1
./mysql-test/mysql-test-run-shell: $MYSQLADMIN --no-defaults -uroot --socket=$MYSQL_TMP_DIR/$ident.sock$3 --connect_timeout=1 ping >> $MYSQL_MANAGER_LOG 2>&1
./mysql-test/mysql-test-run-shell: $MYSQLADMIN --no-defaults -uroot --socket=$MYSQL_TMP_DIR/$slave_ident.sock stop-slave > /dev/null 2>&1
./mysql-test/mysql-test-run: # On QNX, /tmp/dir/master.sock and /tmp/dir//master.sock seem to be
./mysql-test/mysql-test-run: my $sockdir = $opt_tmpdir;
./mysql-test/mysql-test-run: $master->[0]->{'path_sock'}= $opt_socket ? $opt_socket : "/tmp/mysql.sock";
./mysql-test/mtr: # On QNX, /tmp/dir/master.sock and /tmp/dir//master.sock seem to be
./mysql-test/mtr: my $sockdir = $opt_tmpdir;
./mysql-test/mtr: $master->[0]->{'path_sock'}= $opt_socket ? $opt_socket : "/tmp/mysql.sock";
./mysql-test/mysql-test-run.pl: # On QNX, /tmp/dir/master.sock and /tmp/dir//master.sock seem to be
./mysql-test/mysql-test-run.pl: my $sockdir = $opt_tmpdir;
./mysql-test/mysql-test-run.pl: $master->[0]->{'path_sock'}= $opt_socket ? $opt_socket : "/tmp/mysql.sock";
./mysql-test/mysql-stress-test.pl:$opt_server_socket= $opt_server_socket ? $opt_server_socket : "/tmp/mysql.sock";
Linux:>prakash_prasad/bin/mysql-5.0.91 1019>
Now I not sure what changes I have to make to be able to use it.
Thanks in advance
Create your my.cnf wherever you want and start the server with
/path/to/mysqld --defaults-file=/path/to/my.cnf
try the --defaults-extra-file=path option if you can't change the /etc/my.cnf file.
Or, if you only want to change the socket, use: --socket=/tmp/mysql.sock