Skip to content

[Bug] Container "Upgrade" incorrectly locks dynamic IP to static IPAMConfig, causing "Address already in use" on reboot #13627

Description

@WAOR

Contact Information

No response

1Panel Version

2.2.5

Problem Description

Bug Description

When using the "Upgrade" function on the "Containers" page, the underlying API mistakenly reads the container's current runtime dynamic IP (IPAddress) and writes it as the desired static IP (IPAMConfig) into the new container's configuration.

This forces containers that originally acquired IPs dynamically to be bound to a fixed IP after being upgraded via the panel. If the server restarts, Docker's dynamic allocation mechanism may assign this IP to other containers that start first. When this happens, the container with the forced static IP will fail to start, throwing an Address already in use error.

Steps to Reproduce

Steps to Reproduce

  1. Create a custom bridge network (e.g., test-network), or simply use the panel's default 1panel-network.
  2. In the server terminal, use the native docker run command to run a test container and join this network (do not specify a static IP). For example:
    docker run -d --name ip-test --network 1panel-network nginx:latest
  3. Run docker inspect ip-test in the terminal and check the Networks node. At this point, IPAMConfig is null, and IPAddress contains the dynamically assigned IP from Docker (e.g., 172.18.0.5).
  4. In the 1Panel left menu, navigate to the Containers -> Containers list.
  5. Find the ip-test container and click Upgrade in the operation column.
  6. After the upgrade completes, run docker inspect ip-test in the terminal again.
  7. Actual Result: The previously null IPAMConfig has been incorrectly overwritten with the former dynamic IP: {"IPv4Address": "172.18.0.5"}.
  8. Destructive Consequence Verification: Restart the server (or restart the Docker service). If other dynamically-allocated containers happen to start first and claim the .5 IP, the ip-test container (now forced to use a static IP) will immediately fail to start, throwing the error: failed to set up container networking: Address already in use.

The expected correct result

No response

Related log output

Additional Information

Source Code Analysis

The problematic code is located in the buildContainerRecoverNetworkConfig function within agent/app/service/backup_container.go.

When copying network configurations, the current logic fails to strictly distinguish between "the user-defined desired static IP" and "the container's current runtime dynamic IP". The logic is as follows:

if endpoint.IPAMConfig != nil {
	endpointSetting.IPAMConfig = &network.EndpointIPAMConfig{
		IPv4Address:  endpoint.IPAMConfig.IPv4Address,
		IPv6Address:  endpoint.IPAMConfig.IPv6Address,
		LinkLocalIPs: append([]string(nil), endpoint.IPAMConfig.LinkLocalIPs...),
	}
} else if name != "bridge" && (endpoint.IPAddress != "" || endpoint.GlobalIPv6Address != "") {
	// The issue lies in the branch below:
	// If the original container did NOT have a static IP set (IPAMConfig is nil), but has a runtime dynamic IP,
	// the code extracts it and converts it into a static configuration (IPAMConfig) for the new container.
	endpointSetting.IPAMConfig = &network.EndpointIPAMConfig{
		IPv4Address: endpoint.IPAddress,
		IPv6Address: endpoint.GlobalIPv6Address,
	}
}

Suggested Fix

We highly recommend adopting the fix used by other panels like Portainer to strictly separate these two states. During a container upgrade or recreation, if the old container's IPAMConfig was null, the new container's should remain null. This hands the IP allocation responsibility cleanly back to the Docker engine, rather than improperly assigning IPAddress to IPAMConfig.

It is suggested to directly remove the else if branch logic mentioned above.

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions