Search code examples
dockerdocker-machine

Is there a way to force docker-machine to create vm with a specific ip?


Is there a way to force docker-machine to create the docker vm with a specific ip (assuming that ip is available)?


Solution

  • That is actively requested in docker/machine issue 1709

    I want to be able to specify the IP address of a VM (i.e. the value that's listed under "URL" in docker-machine ls) when I create it with docker-machine create.

    I want this because I've been relying on boot2docker's default address of 192.168.59.103, but now it varies from machine to machine.

    The current workaround:

    My virtualbox has dhcp range 192.168.99.100 - 255 and I want to set an IP before 100.

    I've found a simple trick to set a static IP: after create a machine, I run this command and restart the machine:

    echo "ifconfig eth1 192.168.99.50 netmask 255.255.255.0 broadcast 192.168.99.255 up" | docker-machine ssh prova-discovery sudo tee /var/lib/boot2docker/bootsync.sh > /dev/null
    

    This command create a file bootsync.sh that is searched by boot2docker startup scripts and executed.

    Now during machine boot the command is executed and set static IP.

    docker-machine ls
    NAME              ACTIVE   DRIVER       STATE     URL                                      SWARM
    test-1                      -        virtualbox     Running   tcp://192.168.99.50:2376      test-1 (master)
    

    Michele Tedeschi (micheletedeschi) adds

    I've updated the commands with:

    echo "kill `more /var/run/udhcpc.eth1.pid`\nifconfig eth1 192.168.99.50 netmask 255.255.255.0 broadcast 192.168.99.255 up" | docker-machine ssh prova-discovery sudo tee /var/lib/boot2docker/bootsync.sh > /dev/null
    

    then run command (only the first time)

    docker-machine regenerate-certs prova-discovery
    

    now the IP will not be changed by the DHCP

    (replace prova-discovery by the name of your docker-machine)


    Here is the (Windows) script (dmvbf.bat) I now use, based on what is above:

    @echo off
    setlocal enabledelayedexpansion
    set machine=%1
    if "%machine%" == "" (
        echo dmvbf expects a machine name
        exit /b 1
    )
    set ipx=%2
    if "%ipx%" == "" (
        echo dmvbf x missing ^(for 192.168.x.y^)
        exit /b 2
    )
    set ipy=%3
    if "%ipy%" == "" (
        echo dmvbf y missing ^(for 192.168.x.y^)
        exit /b 3
    )
    
    echo kill $(more /var/run/udhcpc.eth1.pid) | docker-machine ssh %machine% sudo tee /var/lib/boot2docker/bootsync.sh >NUL
    echo ifconfig eth1 192.168.%ipx%.%ipy% netmask 255.255.255.0 broadcast 192.168.%ipx%.255 up | docker-machine ssh %machine% sudo tee -a /var/lib/boot2docker/bootsync.sh >NUL
    echo route add default gw <gateway ip address here> | docker-machine ssh %machine% sudo tee -a /var/lib/boot2docker/bootsync.sh >NUL
    
    docker-machine ssh %machine% "sudo cat /var/run/udhcpc.eth1.pid | xargs sudo kill"
    
    docker-machine ssh %machine% "sudo ifconfig eth1 192.168.%ipx%.%ipy% netmask 255.255.255.0 broadcast 192.168.%ipx%.255 up"
    

    (Note: on Windows 10, Monty Wild comments that it is udhcpc.eth0.pid, not udhcpc.eth1.pid)

    I start the vm (docker-machine start <machine-name>), and then:

     dmvbf <machine-name> 99 101
    

    I do that only once.

    At the next docker-machine start <machine-name>, the IP will be 192.168.99.101.