如何使用Dockerfile在MySQL上更改默认IP [英] How to change default IP on MySQL using Dockerfile

查看:166
本文介绍了如何使用Dockerfile在MySQL上更改默认IP的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有一种方法可以使用Dockerfile在MySQL上更改IP?我的应用有问题.

我有此配置:

  let ormConfig:任意;如果(process.env.NODE_ENV ==='test'){//测试环境数据库应该每次都删除.因此,同步对于此配置应为trueormConfig = {类型:"mysql",主机:"0.0.0.0",//host:'localhost',//如果在docker上运行则不需要用户名:"root",密码:"password",数据库:"test_db",同步:是的,dropSchema:是的,实体:['src/models/**/*.ts']};} 别的 {ormConfig = {类型:"mysql",host:'db',//docker服务数据库名称//host:'localhost',//如果在docker上运行则不需要//端口:3306,//如果在docker上运行,则不需要用户名:"root",密码:"password",数据库:"development_db",同步:假,日志记录:是的,实体:['src/models/**/*.ts'],迁移:['db/migrations/**/*.ts'],订阅者:['src/subscribers/**/*.ts'],cli:{EntitySir:"src/models",migrationsDir:"db/migrations",subscriptionsDir:"src/subscribers"}};}导出= ormConfig; 

我正在为我的ORM使用typeorm.在别的块上,我有一个主机名 db ,如果我使用我的应用程序,则可以在连接到数据库时使用它,但是当我尝试运行迁移时,我必须将主机更改为 0.0.0.0 ,发现这是由于docker MySQL容器(server_db映像)引起的:

 容器ID图像命令创建的状态端口名称aaaa4d178537 server_server"docker-entrypoint.s…"大约一个小时前Up大约一个小时0.0.0.0:8000->8000/tcp server_server_1e5021687b86b server_db"docker-entrypoint.s…"大约一个小时前Up大约一个小时0.0.0.0:3306->3306/tcp,33060/tcp server_db_1 

我只是厌倦了在迁移之前和之后进行更改和更改.

有什么想法要使用本地主机吗?或类似 1.2.3.456 这样的自定义IP?

这也是我的docker-compose文件:

 版本:"3.3";服务:D b:内部版本:./db重启:总是env_file:-.env端口:-"3306:3306";网络:-app_network服务器:取决于:-"db"#这对于sql连接很重要.它必须等待mysql建立连接,然后运行此bish建造: .命令:["npm",运行",开发"]重启:总是端口:-"8000:8000";数量:-/server/node_modules/#由于bcrypt elm错误而添加了此内容-类型:绑定来源: .目标:/server#此名称来自dockerfile workdir网络:-app_network网络:app_network:数量:app_volume: 

和我的数据库Dockerfile

 从FROM mysql:8.0.18展览3306复制./init_db.sql/docker-entrypoint-initdb.d/ 

更新

要回答@ckaserer的问题,

您从哪里运行迁移?例如您是否要从工作站/泊坞窗主机连接到mysql容器?

我使用命令 npm run migration:run

通过npm在容器外部运行它

您可以共享任何错误日志吗?

错误是说无法连接到 db:3306 ,这就是为什么我必须将其更改为 0.0.0.0:3306 的原因.

您能否阐明您的迁移工作流程及其失败之处?(包括从哪个系统执行该代码,例如容器x,工作站等).

使用typeOrm cli在容器外部进行迁移,我创建了一个迁移,然后cli将检查我的 ormconfig.ts 并将检查else块的类型和主机.(我不确定这是否是您的要求)

更新

如果我运行迁移,则会出现错误:

错误:getaddrinfo ENOTFOUND db db db:3306 IP:Port是问题.

链接到代码存储库: https://github.com/artoodeeto/ggpo-server

解决方案

验证

检查在容器运行时是否可以在主机上重现以下内容.

1)启动您的应用

只需执行 docker-compose up

2)连接到数据库

尝试从这样的主机连接到mysql数据库

 <代码> mysql -u root -ppassword -h 127.0.0.1mysql:[警告]在命令行界面上使用密码可能不安全.欢迎使用MySQL监视器.命令以;结尾;或\ g.您的MySQL连接ID为9服务器版本:8.0.18 MySQL社区服务器-GPL版权所有(c)2000、2019,Oracle和/或其分支机构.版权所有.Oracle是Oracle Corporation和/或其子公司的注册商标.会员.其他名称可能是其各自的商标拥有者.输入帮助;"或'\ h'寻求帮助.键入"\ c"以清除当前输入语句.mysql>显示数据库;#+ -------------------- +|数据库|+ -------------------- +|development_db ||information_schema ||mysql ||performance_schema ||production_db ||sys ||test_db |+ -------------------- +一组7列(0.01秒) 

但是为什么行得通呢?

这里有几件事.首先,您的 ormconfig.ts 对容器中的应用程序是正确的.您的 server 容器要连接到 db 容器.这样可行.在您的docker-compose文件中,您将 db 端口 3306 显式公开给主机上的所有可用接口.您可以通过运行

进行检查

  docker容器ls8b5c4dc41892 ggpo-server_server"docker-entrypoint.s…" 47小时前向上5秒0.0.0.0:8000->8000/tcp ggpo-server_server_1a0ca405d8020 ggpo-server_db"docker-entrypoint.s…" 47小时前向上6秒0.0.0.0:3306->3306/tcp,33060/tcp ggpo-server_db_1 

这表示您的主机上的数据库位于 127.0.0.1:3306 [HOST-IP]:3306 上.这就是为什么以前的mysql connect与 127.0.0.1 .

一起工作的原因.

但是为什么我的迁移无法正常工作?

我们在这里!就像我说的那样,您的 ormconfig.ts 对于容器中的应用程序是正确的-但如果您要从主机连接到数据库,则不是.您的主机不知道DNS名称 db ,因此您的 ormconfig.ts 无法使用.为了从主机访问它,您需要 host:localhost ,要使服务器正常工作,您需要 host:db .但是您不能同时设置两者.因此,您可能需要引入一些额外的env配置,以区分这两种情况.

  if(process.env.NODE_ENV ==='test'){//测试环境数据库...}否则,如果(process.env.NODE_ENV ==='local'){//主机名为localhost的新配置} 别的 {//默认} 


从9.01.2020起的原始答案

否,您无法为dockerfile中的映像分配固定的IP.由于IP必须是唯一的,因此这将破坏可移植性和可伸缩性.

在这种情况下,您需要将 host 绑定到 0.0.0.0 .它将mysql服务绑定到所有可用的网络接口.在您的情况下,容器中的 localhost app_network .

因此,您可以从 app_network 内的任何其他容器访问该容器,也可以进入 db 容器并通过mysql连接直接执行迁移到<代码>本地主机.

从工作站访问数据库

您快到了.您已经在 docker-compose.yml 中具有 db 的端口暴露定义.

 版本:"3.3"服务:D b:端口:-"3306:3306" 

但是,您不能通过外部名称访问容器.端口暴露定义 port 告诉docker将主机在 3306 上获得的所有流量转发到端口 3306 上的 db 容器中.代码>.就是说,因此,您可以使用主机IP或主机名从主机访问 db ,因为您已经在运行容器的机器上,只需使用 localhost 127.0.0.1 .

您需要更改用于迁移的ormconfig.ts.特别是从 db localhost host 条目值.

  {"type":"mysql","host":"localhost",端口":3306,用户名":测试","password":测试",数据库":测试"} 

那应该可以解决您的问题.


奖金

1)为什么我不能为图像分配IP

映像未运行,因此没有IP分配.
但是,您可以像这样在docker-compose.yml中为容器指定一个固定IP

 版本:"2"服务:应用程序:图片:busybox命令:ifconfig网络:app_net:ipv4_address:172.18.18.10网络:app_net:司机:桥driver_opts:com.docker.network.enable_ipv6:假"ipam:驱动程序:默认配置:-子网:172.18.18.0/24网关:172.18.18.1 

2)为什么不应该这样做1)

IP是该特定网络中系统的唯一标识符.那么当您想拥有两个 app 实例时会发生什么?

  docker-compose up --scale app = 2使用驱动程序"bridge"创建网络"playground_app_net"创建Playground_app_1 ...完成正在创建Playground_app_2 ...错误错误:操场上的应用_2无法启动服务应用:b地址已在使用中"错误:对于应用程序无法启动服务应用程序:b地址已在使用中"错误:启动项目时遇到错误. 

Docker告诉您, app 的第一个实例化已经使用了IP地址,并且无法再次分配.

Is there a way to change IP on MySQL using Dockerfile? I have a problem with my app.

I have this configuration:

let ormConfig: any;

if (process.env.NODE_ENV === 'test') {
  // test environment database should be drop every time. so synchronize should be true for this config
  ormConfig = {
    type: 'mysql',
    host: '0.0.0.0',
    // host: 'localhost', // not needed if run on docker
    username: 'root',
    password: 'password',
    database: 'test_db',
    synchronize: true,
    dropSchema: true,
    entities: ['src/models/**/*.ts']
  };
} else {
  ormConfig = {
    type: 'mysql',
    host: 'db', // docker service database name
    // host: 'localhost', // not needed if run on docker
    // port: 3306, // not needed if run on docker
    username: 'root',
    password: 'password',
    database: 'development_db',
    synchronize: false,
    logging: true,
    entities: ['src/models/**/*.ts'],
    migrations: ['db/migrations/**/*.ts'],
    subscribers: ['src/subscribers/**/*.ts'],
    cli: {
      entitiesDir: 'src/models',
      migrationsDir: 'db/migrations',
      subscribersDir: 'src/subscribers'
    }
  };
}

export = ormConfig;

I'm using typeorm for my ORM. On else block I have a host name db this works when connecting to my db if I'm using my application, but when I tried running a migration I have to change the host to 0.0.0.0 and found out that it's because of the docker MySQL container (server_db image):

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
aaaa4d178537        server_server       "docker-entrypoint.s…"   About an hour ago   Up About an hour    0.0.0.0:8000->8000/tcp              server_server_1
e5021687b86b        server_db           "docker-entrypoint.s…"   About an hour ago   Up About an hour    0.0.0.0:3306->3306/tcp, 33060/tcp   server_db_1

I'm just tired of changing and changing it before and after migration.

Any idea just to use localhost? or custom IP like 1.2.3.456 something like that?

Also here's my docker-compose file:

version: "3.3"
services:
  db:
    build: ./db
    restart: always
    env_file:
      - .env
    ports:
      - "3306:3306"
    networks:
      - app_network
  server:
    depends_on:
      - "db" # this is important for sql connection. it has to wait for mysql to establish connection then run this bish
    build: .
    command: ["npm", "run", "dev"]
    restart: always
    ports:
      - "8000:8000"
    volumes:
      - /server/node_modules/ # added this because of bcrypt elm error
      - type: bind
        source: .
        target: /server # this name is from dockerfile workdir
    networks:
      - app_network

networks:
  app_network:
volumes:
  app_volume:

and my db Dockerfile

FROM mysql:8.0.18
EXPOSE 3306
COPY ./init_db.sql /docker-entrypoint-initdb.d/

Update

To answer @ckaserer's question:

Where are you running the migration from? e.g. are you trying to connect from your workstation/docker host to the mysql container?

I'm running it outside the container through npm with a command npm run migration:run

Any error logs you can share?

The error is saying cannot connect to db:3306, that's why I have to change it to 0.0.0.0:3306.

Can you clarify your migration workflow and where it fails? (including from which system it is executed. e.g. container x, workstation,..)

The migration happens outside the container using typeOrm cli, I create a migration, then cli will check my ormconfig.ts and will check the else block for the type and host. (I'm not sure if this is what your asking)

Update

Here's the error if I run the migration:

Error: getaddrinfo ENOTFOUND db db:3306 the IP:Port is the problem. grrrr.

Link to Code repository: https://github.com/artoodeeto/ggpo-server

解决方案

Verify

check if you can reproduce the following on your host while your containers are running.

1) start your app

simply execute docker-compose up

2) connect to db

try to connect to your mysql database from your host machine like this

mysql -u root -ppassword -h 127.0.0.1
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 8.0.18 MySQL Community Server - GPL

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
#+--------------------+
| Database           |
+--------------------+
| development_db     |
| information_schema |
| mysql              |
| performance_schema |
| production_db      |
| sys                |
| test_db            |
+--------------------+
7 rows in set (0.01 sec)

But why does that work?

A few things here. First off, your ormconfig.ts is correct for your application within the container. Your server container wants to connect to db container. That works. In your docker-compose file you explicitly exposed the db port 3306 to all available interfaces on your host. You can check that by running

docker container ls
8b5c4dc41892        ggpo-server_server   "docker-entrypoint.s…"   47 hours ago        Up 5 seconds        0.0.0.0:8000->8000/tcp              ggpo-server_server_1
a0ca405d8020        ggpo-server_db       "docker-entrypoint.s…"   47 hours ago        Up 6 seconds        0.0.0.0:3306->3306/tcp, 33060/tcp   ggpo-server_db_1

This translates to your database being available on your host at 127.0.0.1:3306 and [HOST-IP]:3306. This is why the previous mysql connect worked with 127.0.0.1.

But why does my migration not work?

Here we go! Like I stated, your ormconfig.tsis correct for your app within the container - but not if you want to connect to the database from your host. your host does not know about the DNS name db so your ormconfig.ts will not work. In order to access it from your host you need host: localhost, and for your server to work you need host: db. But you can't set both. Therefore you might want to introduce some kind of additional env config that distinguishes between the 2 scenarios.

if (process.env.NODE_ENV === 'test') {
  // test environment database
  ...
} else if (process.env.NODE_ENV === 'local') {
  // new config with host: localhost
} else {
  // default
}


Original answer from 9.01.2020

No, you can not assign a fixed IP to an image in your dockerfile. This would break portability and scalability since the IP needs to be unique.

The host binding to 0.0.0.0 is what you need in that case. It binds the mysql service to all available network interfaces. In your case to localhost and app_network within the container.

Therefore you are able to reach the container from any other container inside your app_network or you could go into the db container and execute your migration directly via mysql connection to localhost.

access to the db from your workstation

You are almost there. You already have the port exposure definition for your db in your docker-compose.yml.

version: "3.3"
services:
  db:
    ports:
      - "3306:3306"

However, you can not access the container by its name from the outside world. The port exposure definition port tells docker to forward any traffic that your host gets on 3306 to the db container on port 3306. That said, you can, therefore, access the db from your host by using your hosts IP or hostname, since you are already on the machine that runs the container you can simply use localhost or 127.0.0.1 in your migration.

You need to change the ormconfig.ts that you use for your migration. In particular the host entry value from db to localhost.

{
   "type": "mysql",
   "host": "localhost",
   "port": 3306,
   "username": "test",
   "password": "test",
   "database": "test"
}

That should fix your issue.


Bonus

1) Why can't I assign an IP to an image

An image is not running, therefore no IP assignment.
You can, however, specify a fixed IP to your container in your docker-compose.yml like this

version: '2'

services:
  app:
    image: busybox
    command: ifconfig
    networks:
      app_net:
        ipv4_address: 172.18.18.10

networks:
  app_net:
    driver: bridge
    driver_opts:
      com.docker.network.enable_ipv6: "false"
    ipam:
      driver: default
      config:
      - subnet: 172.18.18.0/24
        gateway: 172.18.18.1

2) why you should not do 1)

An IP is a unique identifier of a system in that particular network. So what happens when you would like to have 2 instances of app?

docker-compose up --scale app=2
Creating network "playground_app_net" with driver "bridge"
Creating playground_app_1 ... done
Creating playground_app_2 ... error

ERROR: for playground_app_2  Cannot start service app: b'Address already in use'

ERROR: for app  Cannot start service app: b'Address already in use'
ERROR: Encountered errors while bringing up the project.

Docker tells you that the IP address is already in use by the first instantiation of app and can not be assigned again.

这篇关于如何使用Dockerfile在MySQL上更改默认IP的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆