Skip to content

Commit c721998

Browse files
authored
Merge pull request #16 from koyeb/feat/add-private-container-registries-support
add registry_secret parameter for private container images
2 parents 1076ba6 + 924ffba commit c721998

2 files changed

Lines changed: 29 additions & 4 deletions

File tree

koyeb/sandbox/sandbox.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ def create(
112112
idle_timeout: int = 300,
113113
enable_tcp_proxy: bool = False,
114114
privileged: bool = False,
115+
registry_secret: Optional[str] = None,
115116
_experimental_enable_light_sleep: bool = False,
116117
) -> Sandbox:
117118
"""
@@ -136,6 +137,8 @@ def create(
136137
- If None: uses default values
137138
enable_tcp_proxy: If True, enables TCP proxy for direct TCP access to port 3031
138139
privileged: If True, run the container in privileged mode (default: False)
140+
registry_secret: Name of a Koyeb secret containing registry credentials for
141+
pulling private images. Create the secret via Koyeb dashboard or CLI first.
139142
_experimental_enable_light_sleep: If True, uses idle_timeout for light_sleep and sets
140143
deep_sleep=3900. If False, uses idle_timeout for deep_sleep (default: False)
141144
@@ -145,6 +148,16 @@ def create(
145148
Raises:
146149
ValueError: If API token is not provided
147150
SandboxTimeoutError: If wait_ready is True and sandbox does not become ready within timeout
151+
152+
Example:
153+
>>> # Public image (default)
154+
>>> sandbox = Sandbox.create()
155+
156+
>>> # Private image with registry secret
157+
>>> sandbox = Sandbox.create(
158+
... image="ghcr.io/myorg/myimage:latest",
159+
... registry_secret="my-ghcr-secret"
160+
... )
148161
"""
149162
if api_token is None:
150163
api_token = os.getenv("KOYEB_API_TOKEN")
@@ -165,6 +178,7 @@ def create(
165178
idle_timeout=idle_timeout,
166179
enable_tcp_proxy=enable_tcp_proxy,
167180
privileged=privileged,
181+
registry_secret=registry_secret,
168182
_experimental_enable_light_sleep=_experimental_enable_light_sleep,
169183
)
170184

@@ -193,6 +207,7 @@ def _create_sync(
193207
idle_timeout: int = 300,
194208
enable_tcp_proxy: bool = False,
195209
privileged: bool = False,
210+
registry_secret: Optional[str] = None,
196211
_experimental_enable_light_sleep: bool = False,
197212
) -> Sandbox:
198213
"""
@@ -217,7 +232,9 @@ def _create_sync(
217232
app_id = app_response.app.id
218233

219234
env_vars = build_env_vars(env)
220-
docker_source = create_docker_source(image, [], privileged=privileged)
235+
docker_source = create_docker_source(
236+
image, [], privileged=privileged, image_registry_secret=registry_secret
237+
)
221238
deployment_definition = create_deployment_definition(
222239
name=name,
223240
docker_source=docker_source,
@@ -850,6 +867,7 @@ async def create(
850867
idle_timeout: int = 300,
851868
enable_tcp_proxy: bool = False,
852869
privileged: bool = False,
870+
registry_secret: Optional[str] = None,
853871
_experimental_enable_light_sleep: bool = False,
854872
) -> AsyncSandbox:
855873
"""
@@ -874,6 +892,8 @@ async def create(
874892
- If None: uses default values
875893
enable_tcp_proxy: If True, enables TCP proxy for direct TCP access to port 3031
876894
privileged: If True, run the container in privileged mode (default: False)
895+
registry_secret: Name of a Koyeb secret containing registry credentials for
896+
pulling private images. Create the secret via Koyeb dashboard or CLI first.
877897
_experimental_enable_light_sleep: If True, uses idle_timeout for light_sleep and sets
878898
deep_sleep=3900. If False, uses idle_timeout for deep_sleep (default: False)
879899
@@ -906,6 +926,7 @@ async def create(
906926
idle_timeout=idle_timeout,
907927
enable_tcp_proxy=enable_tcp_proxy,
908928
privileged=privileged,
929+
registry_secret=registry_secret,
909930
_experimental_enable_light_sleep=_experimental_enable_light_sleep,
910931
),
911932
)

koyeb/sandbox/utils.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212

1313
from koyeb.api import ApiClient, Configuration
1414
from koyeb.api.api import AppsApi, CatalogInstancesApi, InstancesApi, ServicesApi
15-
from koyeb.api.exceptions import ApiException, NotFoundException
1615
from koyeb.api.models.deployment_definition import DeploymentDefinition
1716
from koyeb.api.models.deployment_definition_type import DeploymentDefinitionType
1817
from koyeb.api.models.deployment_env import DeploymentEnv
@@ -26,7 +25,6 @@
2625
DeploymentScalingTargetSleepIdleDelay,
2726
)
2827
from koyeb.api.models.docker_source import DockerSource
29-
from koyeb.api.models.instance_status import InstanceStatus
3028
from koyeb.api.models.proxy_port_protocol import ProxyPortProtocol
3129

3230
# Setup logging
@@ -137,7 +135,10 @@ def build_env_vars(env: Optional[Dict[str, str]]) -> List[DeploymentEnv]:
137135

138136

139137
def create_docker_source(
140-
image: str, command_args: List[str], privileged: Optional[bool] = None
138+
image: str,
139+
command_args: List[str],
140+
privileged: Optional[bool] = None,
141+
image_registry_secret: Optional[str] = None,
141142
) -> DockerSource:
142143
"""
143144
Create Docker source configuration.
@@ -146,6 +147,8 @@ def create_docker_source(
146147
image: Docker image name
147148
command_args: Command and arguments to run (optional, empty list means use image default)
148149
privileged: If True, run the container in privileged mode (default: None/False)
150+
image_registry_secret: Name of the secret containing registry credentials
151+
for pulling private images
149152
150153
Returns:
151154
DockerSource object
@@ -155,6 +158,7 @@ def create_docker_source(
155158
command=command_args[0] if command_args else None,
156159
args=list(command_args[1:]) if len(command_args) > 1 else None,
157160
privileged=privileged,
161+
image_registry_secret=image_registry_secret,
158162
)
159163

160164

0 commit comments

Comments
 (0)