How to change default port of mysql-server docker image - mysql

I would like to run mysql/mysql-server image in 3 different containers on the same host (End goal is to have innodb cluster running on the host for demo project). And instead of using bridge network and port mapping, I want the containers to start in host network mode.
But, since all 3 containers will be running on same host, I can't have more than one container using same host port.
This is the docker compose file
version: '3'
services:
mysql:
image: mysql/mysql-server
network_mode: "host"
Is it possible to modify docker compose file to achieve my objective? Any pointers would be really helpful!

Host networking is almost never necessary and it disables some core Docker features, like port remapping. If you remove the network_mode: host setting you can pick which host port is used without changing the underlying image at all.
version: '3'
services:
mysql:
image: mysql/mysql-server
ports:
# You pick the first (host) port.
# Second port is the port the container process uses,
# and is usually fixed per image.
- '3305:3306'
Host networking also disables normal inter-container communication as described in Networking in Compose. Unless you're specifically trying to manage the host's network or you have a truly large number of ports you're listening to (like thousands) you should use the default ("bridge") networking. The only downside is that other containers won't be on the host name localhost, but that should just be a matter of providing appropriate configuration to your service.

You can pass --port=3305 in the command.
version: '3'
services:
mysql:
image: mysql/mysql-server
network_mode: "host"
command: --port=3305

Related

Why won't TeamCity connect to MySQL when using docker-compose?

I'm trying to get TeamCity server running using docker-compose. Here's my compose file:
version: '3'
services:
db:
image: mysql
container_name: teamcity-db
restart: unless-stopped
env_file: .env
environment:
- MYSQL_DATABASE=teamcity
volumes:
- mysql:/var/lib/mysql
command: '--default-authentication-plugin=mysql_native_password'
teamcity:
depends_on:
- db
image: jetbrains/teamcity-server
container_name: teamcity
restart: unless-stopped
volumes:
- datadir:/data/teamcity_server/datadir
- logs:/opt/teamcity/logs
ports:
- "8111:8111"
volumes:
mysql:
datadir:
logs:
I've been successful getting wordpress set up using a very similar technique, and I can run phpMyAdmin and link it to the MySQL container and see the database, so its there.
When I browse to the teamcity web address, it shows me the initial setup screen as expected. I tell it to use MySQL and I put in 'root' as teh username and my MySQL root password. Teamcity then shows this:
I'm sure it's something simple but I just can't see what's wrong. Any ideas?
Solved! Here is my solution and some other learnings.
The problem was that I was telling TeamCity to use 'localhost' as the database server URL. This seems intuitive because all the services are on the same machine, but is incorrect. It is as if each container is its own host and so 'localhost' is specific to each container. 'localhost' inside a container refers to the container itself, not the host machine or any other container. So 'localhost' on the teamcity service refers to the teamcity server, not the database server, and that's why it couldn't connect.
The correct address for the database server based on my docker-compose.yml file is db (the service name of the database container). The service name becomes the host name for that container and docker resolves these as DNS names correctly within the composed group.
Also note: the default virtual network is created implicitly by docker-compose and allows all of the containers in the composed group to communicate with each other. The name of this network derives from the folder where the docker-compose.yml file is located (in my case ~/projects/teamcity) so I get a network called teamcity_default. All servers on this private vitual network are visible to each other with no further configuration needed.
The teamcity server container explicitly exposes port 8111 on the host's network interface, so it is the only container visible to the outside world. You do not need to (and probably should not) expose ports if you only need the servers to talk to each other. For example, the database server does not need to have a ports entry because it is automatically exposed on the private inter-container network. This is great for security because all the back-end services are hidden from the physical LAN and therefore the Internet.

How can a Spring app in docker access mysql in host or cloud mysql?

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

Docker - secure mysql configuration

I want to make a separate docker container for mine mysql database which will run for my production and test environment. The problem is that it has the potential to exposes the port number and environment values to for example hackers who have gained access to the container.
How can I write a secure mysql image that doesn't show the port number and environment variables?
UPDATE
I have created a local .env file and used variables in mine docker-compose.yml.
docker-compose.yml
version: '3.1'
services:
mysql:
image: mysql:5.6
ports:
- 3306
environment:
- DB_DATABASE=${DB_DATABASE}
- DB_USERNAME=${DB_USERNAME}
- DB_PASSWORD=${DB_PASSWORD}

How to connect to a MySQL Docker Container via SSH?

When I try to tunnel via SSH to the Host Mashine (vServer) and then try to connect via the internal docker Container-IP then I can't connect to MySQL.
This is my docker-compose file.
version: '2'
services:
mysql:
build: ./mysql
environment:
MYSQL_ROOT_PASSWORD: test
volumes:
- ./db:/var/lib/mysql
The only solution I found was to forward the MySQL-Port of the mysql container to the Host-Mashine.
version: '2'
services:
mysql:
build: ./mysql
environment:
MYSQL_ROOT_PASSWORD: test
volumes:
- ./db:/var/lib/mysql
ports:
- 3306:3306
Then I am able to connect via the Host IP to MySQL but this is without SSH its direct via TCP and the port.
This is a No-Go for me to bring the MySQL Service into the internet.
Reasons can be found here https://security.stackexchange.com/questions/63881/is-it-not-safe-to-open-mysqls-port-to-the-internet why it is not a good practice to bring your mysql port into the internet.
So what is a good practice to connect to my docker mysql container with SSH but keep the mysql ports closed?
One simple way is to bind the MySQL port only to the localhost address. That assumes the host has a mysql client available outside of Docker.
ports:
- 127.0.0.1:3306:3306
You could also omit the ports section completely (no port binding at all), and use the mysql client that's already inside the container.
docker-compose exec mysql bash
Then run the mysql command inside the container to do whatever queries you want to do.
An easy way to achieve this is to forward the ssh port of the docker conatiner to some port on your host, i.e.
ports:
- 22:<some free host port>
and then access the container via ssh to the host port you used. Note, that it is a bad idea to use port 22, since that will cause a conflict with the ssh server running on your host.

Get database address with Docker

I use docker-compose with the following docker-compose.yml:
web_db:
image: mariadb:latest
restart: always
volumes:
- ./var/mysql:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: X
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: X
MYSQL_ROOT_PASSWORD: X
web_front:
image: nginx
restart: always
ports:
- 80:80
links:
- web_fpm
volumes:
- ./www:/var/www/html:rw
- ./etc/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
web_fpm:
build: ./PHP-FPM/
restart: always
links:
- web_db:mysql
volumes:
- ./www:/var/www/html
When configuring Wordpress (manually downloaded in nginx root directory), I'm asked for the address of the database. I've tried localhost, but it doesn't work.
PS: I know there are Wordpress images for Docker, but they have the full stack (nginx + PHP) and I don't like it, so don't propose them. ;)
Try 'web_db' instead of localhost
https://docs.docker.com/compose/compose-file/
Containers for the linked service will be reachable at a hostname identical to the alias, or the service name if no alias was specified.
You need to reference mysql because in your compose file you have linked your container to the web_db container and given it an alias of 'mysql'. The web_fpm container will have a record in it's hosts file for mysql which will point to the web_db container.
Alternatively, if you just want to get the ip to enter manually, just run docker inspect <web_db_container_id>
edit: You will want to put in the IP of the host machine along with port 3306 and here is why.
When starting a container with Docker it is started using an IP assigned from the Docker. These are all accessible to docker via the docker0 bridged network. Docker in turn makes those accessible to the host machine by bridging the docker0 NIC on the host machine with the host machines eth0/1 ect.
When you EXPOSE a port explicitly via docker run -td -p <some external port>:<some internal port> Docker opens that port up in the host IPTables so it is accessible on the local network. If you do not explicitly open the port but it is exposed in the container (the docker file will say EXPOSE 3306 for MySQL in its Dockerfile.) then the container is only available to the machine.
Now, when working with Docker containers it's important to know this because when you do a link with docker-compose you are only telling that container where another container is on the local docker network. This only helps if you have containers that start and are looking for a dependent container.
To summarize, when containers are started they are started with a Docker IP that is only used by Docker and bridged back to the host machine via docker0, and this is key. Docker isolates those IP and forces you to either open the ports on the machine to access via your local network.
Back to your question and why you need to pass it the host IP and port 3306.
You need to do this because you are making making a request on your network. If you put in localhost it will not work because the container is not really running on localhost it's running on some 172.17.42.x address so telling WordPress it's on localhost, it's not. It is however on at the host machines IP because the host machine is bridged to docker0. This is why you have to give it the host machines IP. Because you network can't resolve the 172.17 address since that is specific to Docker and specific to that machines containers. This is very fundamental to Docker networking and important to understand. See this article for more information.