Skip to content

Commit

Permalink
Add static binding to webserver localhost port
Browse files Browse the repository at this point in the history
  • Loading branch information
rfay committed Mar 20, 2019
1 parent 22419d4 commit d4e31e8
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 10 deletions.
26 changes: 18 additions & 8 deletions pkg/ddevapp/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"io/ioutil"
"os"
"path/filepath"
"strconv"
"strings"

"github.com/drud/ddev/pkg/globalconfig"
Expand All @@ -22,7 +21,6 @@ import (
"github.com/drud/ddev/pkg/output"
"github.com/drud/ddev/pkg/util"
"github.com/drud/ddev/pkg/version"
"github.com/phayes/freeport"
log "github.com/sirupsen/logrus"
"gopkg.in/yaml.v2"
)
Expand Down Expand Up @@ -78,11 +76,16 @@ func NewApp(AppRoot string, provider string) (*DdevApp, error) {
app.RouterHTTPSPort = DdevDefaultRouterHTTPSPort
app.MariaDBVersion = version.MariaDBDefaultVersion

dbPort, err := freeport.GetFreePort()
var err error
app.HostWebserverPort, err = util.GetFreePort()
if err != nil {
return app, fmt.Errorf("Failed to find a free port for ddev-dbserver container binding: %v", err)
return app, err
}

app.HostDBPort, err = util.GetFreePort()
if err != nil {
return app, err
}
app.HostDBPort = strconv.Itoa(dbPort)

// These should always default to the latest image/tag names from the Version package.
app.WebImage = version.GetWebImage()
Expand Down Expand Up @@ -150,10 +153,17 @@ func (app *DdevApp) WriteConfig() error {
appcopy.BgsyncImage = ""
}

// We now want to reserve the port we're writing for DBport so it doesn't
// We now want to reserve the port we're writing for HostDBPort and HostWebserverPort and so they don't
// accidentally get used for other projects.
if !util.ArrayContainsString(globalconfig.DdevGlobalConfig.UsedHostDBPorts, app.HostDBPort) {
globalconfig.DdevGlobalConfig.UsedHostDBPorts = append(globalconfig.DdevGlobalConfig.UsedHostDBPorts, app.HostDBPort)
if !util.ArrayContainsString(globalconfig.DdevGlobalConfig.UsedHostPorts, app.HostDBPort) {
globalconfig.DdevGlobalConfig.UsedHostPorts = append(globalconfig.DdevGlobalConfig.UsedHostPorts, app.HostDBPort)
err := globalconfig.WriteGlobalConfig(globalconfig.DdevGlobalConfig)
if err != nil {
return err
}
}
if !util.ArrayContainsString(globalconfig.DdevGlobalConfig.UsedHostPorts, app.HostWebserverPort) {
globalconfig.DdevGlobalConfig.UsedHostPorts = append(globalconfig.DdevGlobalConfig.UsedHostPorts, app.HostWebserverPort)
err := globalconfig.WriteGlobalConfig(globalconfig.DdevGlobalConfig)
if err != nil {
return err
Expand Down
2 changes: 2 additions & 0 deletions pkg/ddevapp/ddevapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ type DdevApp struct {
WorkingDir map[string]string `yaml:"working_dir,omitempty"`
OmitContainers []string `yaml:"omit_containers,omitempty"`
HostDBPort string `yaml:"host_db_port"`
HostWebserverPort string `yaml:"host_webserver_port"`
}

// GetType returns the application type as a (lowercase) string
Expand Down Expand Up @@ -934,6 +935,7 @@ func (app *DdevApp) DockerEnv() {
"DDEV_BGSYNCIMAGE": app.BgsyncImage,
"DDEV_APPROOT": app.AppRoot,
"DDEV_HOST_DB_PORT": app.HostDBPort,
"DDEV_HOST_WEBSERVER_PORT": app.HostWebserverPort,
"DDEV_DOCROOT": app.Docroot,
"DDEV_IMPORTDIR": app.ImportDir,
"DDEV_URL": app.GetHTTPURL(),
Expand Down
7 changes: 6 additions & 1 deletion pkg/ddevapp/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ services:
- db:db
# ports is list of exposed *container* ports
ports:
- "80"
- "127.0.0.1:$DDEV_HOST_WEBSERVER_PORT:80"
- "{{ .MailhogPort }}"
environment:
- DDEV_URL=$DDEV_URL
Expand Down Expand Up @@ -245,6 +245,11 @@ const ConfigInstructions = `
# Note that these containers can also be omitted globally in the
# ~/.ddev/global_config.yaml or with the "ddev config global" command.
# host_webserver_port: "6660"
# The host port binding for the ddev-webserver can be explicitly specified. It's static
# after first configuration. This is not used by most people, most people use the *router* instead
# of the localhost port.
# host_db_port: "6667"
# The host port binding for the ddev-dbserver can be explicitly specified. It's normally static
# after first configuration
Expand Down
2 changes: 1 addition & 1 deletion pkg/globalconfig/global_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ type GlobalConfig struct {
OmitContainers []string `yaml:"omit_containers"`
InstrumentationOptIn bool `yaml:"instrumentation_opt_in"`
LastUsedVersion string `yaml:"last_used_version"`
UsedHostDBPorts []string `yaml:"used_host_db_ports"`
UsedHostPorts []string `yaml:"used_host_ports"`
DeveloperMode bool `yaml:"developer_mode,omitempty"`
}

Expand Down
21 changes: 21 additions & 0 deletions pkg/util/utils.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package util

import (
"fmt"
"github.com/drud/ddev/pkg/globalconfig"
"github.com/phayes/freeport"
"math/rand"
"os"
osexec "os/exec"
Expand Down Expand Up @@ -175,3 +178,21 @@ func GetFirstWord(s string) string {
arr := strings.Split(s, " ")
return arr[0]
}

// GetFreePort gets an ephemeral port currently available, but also not
// listed in DdevGlobalConfig.UsedHostPorts
func GetFreePort() (string, error) {
// Limit tries arbitrarily. It will normally succeed first try.
for i := 1; i < 1000; i++ {
port, err := freeport.GetFreePort()
strPort := strconv.Itoa(port)
if err != nil {
return "-1", err
}
if ArrayContainsString(globalconfig.DdevGlobalConfig.UsedHostPorts, strPort) {
continue
}
return strPort, nil
}
return "-1", fmt.Errorf("GetFreePort() failed to find a free port")
}

4 comments on commit d4e31e8

@t3easy
Copy link

@t3easy t3easy commented on d4e31e8 Mar 21, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does the webserver need a port bing to the host at all, if the router handles the request to port 80 and proxy it to the webserver?

@rfay
Copy link
Owner Author

@rfay rfay commented on d4e31e8 Mar 21, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great question, I was long surprised by that too. But lots of people use it as a shortcut for various things, including debugging. It is fantastic for debugging the router of course, because if you can hit the localhost-port mount, you know thjings are generally working. We long had the localhost port there, but didn't ever add it to ddev describe until a year or so ago, and it seemed people liked it.

@t3easy
Copy link

@t3easy t3easy commented on d4e31e8 Mar 21, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, so removing it would be a breaking change?!
Just thought if someone need it for a special use case this could be done by the override.

@rfay
Copy link
Owner Author

@rfay rfay commented on d4e31e8 Mar 21, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, people use it enough that we're not going to remove it, this actually adds more explicit support. I wasn't going to touch http in this PR until I realized that OP ddev#941 especially called that out.

Please sign in to comment.