portainer/app/docker/views/containers/create/createcontainer.html

825 lines
43 KiB
HTML
Raw Normal View History

<rd-header>
<rd-header-title title-text="Create container"></rd-header-title>
<rd-header-content> <a ui-sref="docker.containers">Containers</a> &gt; Add container </rd-header-content>
</rd-header>
<information-panel title-text="Caution" ng-if="state.mode == 'duplicate'">
<span class="small">
<p class="text-muted">
<i class="fa fa-exclamation-circle orange-icon" aria-hidden="true" style="margin-right: 2px;"></i>
The new container may fail to start if the image is changed, and settings from the previous container aren't compatible. Common causes include entrypoint, cmd or
<a href="http://portainer.readthedocs.io/en/stable/agent.html" target="_blank">other settings</a> set by an image.
</p>
</span>
</information-panel>
<div class="row">
<div class="col-lg-12 col-md-12 col-xs-12">
<rd-widget>
<rd-widget-body>
<form class="form-horizontal" autocomplete="off">
<!-- name-input -->
<div class="form-group">
<label for="container_name" class="col-sm-1 control-label text-left">Name</label>
<div class="col-sm-11">
<input type="text" class="form-control" ng-model="config.name" id="container_name" placeholder="e.g. myContainer" />
</div>
</div>
<!-- !name-input -->
<div class="col-sm-12 form-section-title">
Image configuration
</div>
fix(app): registry push-pull features overhaul (#3393) * feat(registry): registry or direct url selector * feat(app): push pull container creation * feat(app): push pull container duplicate * feat(app): push pull container details recreate * feat(app): push pull container details commit * feat(app): push pull images * feat(app): push pull image tag * feat(app): push pull image push * feat(app): push pull image pull * feat(app): push pull service creation * feat(app): push pull templates create container * feat(app): push pull templates create stacks * feat(app): push pull template edit * feat(app): push pull service details update * fix(app): refactor registry selector + registry auto select * feat(app): remove autocomplete on registry selector * style(image-registry): reword simple/advanced mode * Revert "feat(app): remove autocomplete on registry selector" This reverts commit 97ec2ddd62715405c4089bd2c0cdda4028263d94. * refactor(registry-selector): reverse registry and image fields * feat(app): autocomplete on registry selector * feat(registry-selector): change gitlab registry autocomplete * feat(registry-selector): autocomplete for dockerhub * feat(registry-selector): gitlab url based on locked value instead of name * fix(registry-selector): gitlab registries URL are not modified anymore * fix(registry-selector): change gitlab image autofill on duplicate * fix(registry-selector): gitlab registries now only suggest their own images and not all from gitlab * fix(registry-selector): psuh pull issues with gitlab registries * fix(registry-selector): dockerhub registry selection on duplicate for dockerhub images * fix(templates): registry retrieval for template * feat(images): add autocomplete on image pull panel * fix(registry-selector): add latest tag when no tag is specified * fix(registry-selector): latest tag now applied for non gitlab registries
2019-11-27 22:36:39 +00:00
<div ng-if="!formValues.RegistryModel.Registry && fromContainer">
<i class="fa fa-exclamation-triangle orange-icon" aria-hidden="true"></i>
<span class="small text-danger" style="margin-left: 5px;">
The Docker registry for the <code>{{ config.Image }}</code> image is not registered inside Portainer, you will not be able to create a container. Please register that
registry first.
</span>
</div>
fix(app): registry push-pull features overhaul (#3393) * feat(registry): registry or direct url selector * feat(app): push pull container creation * feat(app): push pull container duplicate * feat(app): push pull container details recreate * feat(app): push pull container details commit * feat(app): push pull images * feat(app): push pull image tag * feat(app): push pull image push * feat(app): push pull image pull * feat(app): push pull service creation * feat(app): push pull templates create container * feat(app): push pull templates create stacks * feat(app): push pull template edit * feat(app): push pull service details update * fix(app): refactor registry selector + registry auto select * feat(app): remove autocomplete on registry selector * style(image-registry): reword simple/advanced mode * Revert "feat(app): remove autocomplete on registry selector" This reverts commit 97ec2ddd62715405c4089bd2c0cdda4028263d94. * refactor(registry-selector): reverse registry and image fields * feat(app): autocomplete on registry selector * feat(registry-selector): change gitlab registry autocomplete * feat(registry-selector): autocomplete for dockerhub * feat(registry-selector): gitlab url based on locked value instead of name * fix(registry-selector): gitlab registries URL are not modified anymore * fix(registry-selector): change gitlab image autofill on duplicate * fix(registry-selector): gitlab registries now only suggest their own images and not all from gitlab * fix(registry-selector): psuh pull issues with gitlab registries * fix(registry-selector): dockerhub registry selection on duplicate for dockerhub images * fix(templates): registry retrieval for template * feat(images): add autocomplete on image pull panel * fix(registry-selector): add latest tag when no tag is specified * fix(registry-selector): latest tag now applied for non gitlab registries
2019-11-27 22:36:39 +00:00
<div ng-if="formValues.RegistryModel.Registry || !fromContainer">
<!-- image-and-registry -->
<por-image-registry
fix(app): registry push-pull features overhaul (#3393) * feat(registry): registry or direct url selector * feat(app): push pull container creation * feat(app): push pull container duplicate * feat(app): push pull container details recreate * feat(app): push pull container details commit * feat(app): push pull images * feat(app): push pull image tag * feat(app): push pull image push * feat(app): push pull image pull * feat(app): push pull service creation * feat(app): push pull templates create container * feat(app): push pull templates create stacks * feat(app): push pull template edit * feat(app): push pull service details update * fix(app): refactor registry selector + registry auto select * feat(app): remove autocomplete on registry selector * style(image-registry): reword simple/advanced mode * Revert "feat(app): remove autocomplete on registry selector" This reverts commit 97ec2ddd62715405c4089bd2c0cdda4028263d94. * refactor(registry-selector): reverse registry and image fields * feat(app): autocomplete on registry selector * feat(registry-selector): change gitlab registry autocomplete * feat(registry-selector): autocomplete for dockerhub * feat(registry-selector): gitlab url based on locked value instead of name * fix(registry-selector): gitlab registries URL are not modified anymore * fix(registry-selector): change gitlab image autofill on duplicate * fix(registry-selector): gitlab registries now only suggest their own images and not all from gitlab * fix(registry-selector): psuh pull issues with gitlab registries * fix(registry-selector): dockerhub registry selection on duplicate for dockerhub images * fix(templates): registry retrieval for template * feat(images): add autocomplete on image pull panel * fix(registry-selector): add latest tag when no tag is specified * fix(registry-selector): latest tag now applied for non gitlab registries
2019-11-27 22:36:39 +00:00
model="formValues.RegistryModel"
ng-if="formValues.RegistryModel.Registry"
auto-complete="true"
label-class="col-sm-1"
input-class="col-sm-11"
feat(app): rework private registries and support private registries in kubernetes EE-30 (#5131) * feat(app): rework private registries and support private registries in kubernetes [EE-30] feat(api): backport private registries backend changes (#5072) * feat(api/bolt): backport bolt changes * feat(api/exec): backport exec changes * feat(api/http): backport http/handler/dockerhub changes * feat(api/http): backport http/handler/endpoints changes * feat(api/http): backport http/handler/registries changes * feat(api/http): backport http/handler/stacks changes * feat(api/http): backport http/handler changes * feat(api/http): backport http/proxy/factory/azure changes * feat(api/http): backport http/proxy/factory/docker changes * feat(api/http): backport http/proxy/factory/utils changes * feat(api/http): backport http/proxy/factory/kubernetes changes * feat(api/http): backport http/proxy/factory changes * feat(api/http): backport http/security changes * feat(api/http): backport http changes * feat(api/internal): backport internal changes * feat(api): backport api changes * feat(api/kubernetes): backport kubernetes changes * fix(api/http): changes on backend following backport feat(app): backport private registries frontend changes (#5056) * feat(app/docker): backport docker/components changes * feat(app/docker): backport docker/helpers changes * feat(app/docker): backport docker/views/container changes * feat(app/docker): backport docker/views/images changes * feat(app/docker): backport docker/views/registries changes * feat(app/docker): backport docker/views/services changes * feat(app/docker): backport docker changes * feat(app/kubernetes): backport kubernetes/components changes * feat(app/kubernetes): backport kubernetes/converters changes * feat(app/kubernetes): backport kubernetes/models changes * feat(app/kubernetes): backport kubernetes/registries changes * feat(app/kubernetes): backport kubernetes/services changes * feat(app/kubernetes): backport kubernetes/views/applications changes * feat(app/kubernetes): backport kubernetes/views/configurations changes * feat(app/kubernetes): backport kubernetes/views/configure changes * feat(app/kubernetes): backport kubernetes/views/resource-pools changes * feat(app/kubernetes): backport kubernetes/views changes * feat(app/portainer): backport portainer/components/accessManagement changes * feat(app/portainer): backport portainer/components/datatables changes * feat(app/portainer): backport portainer/components/forms changes * feat(app/portainer): backport portainer/components/registry-details changes * feat(app/portainer): backport portainer/models changes * feat(app/portainer): backport portainer/rest changes * feat(app/portainer): backport portainer/services changes * feat(app/portainer): backport portainer/views changes * feat(app/portainer): backport portainer changes * feat(app): backport app changes * config(project): gitignore + jsconfig changes gitignore all files under api/cmd/portainer but main.go and enable Code Editor autocomplete on import ... from '@/...' fix(app): fix pull rate limit checker fix(app/registries): sidebar menus and registry accesses users filtering fix(api): add missing kube client factory fix(kube): fetch dockerhub pull limits (#5133) fix(app): pre review fixes (#5142) * fix(app/registries): remove checkbox for endpointRegistries view * fix(endpoints): allow access to default namespace * fix(docker): fetch pull limits * fix(kube/ns): show selected registries for non admin Co-authored-by: Chaim Lev-Ari <chiptus@gmail.com> chore(webpack): ignore missing sourcemaps fix(registries): fetch registry config from url feat(kube/registries): ignore not found when deleting secret feat(db): move migration to db 31 fix(registries): fix bugs in PR EE-869 (#5169) * fix(registries): hide role * fix(endpoints): set empty access policy to edge endpoint * fix(registry): remove double arguments * fix(admin): ignore warning * feat(kube/configurations): tag registry secrets (#5157) * feat(kube/configurations): tag registry secrets * feat(kube/secrets): show registry secrets for admins * fix(registries): move dockerhub to beginning * refactor(registries): use endpoint scoped registries feat(registries): filter by namespace if supplied feat(access-managment): filter users for registry (#5191) * refactor(access-manage): move users selector to component * feat(access-managment): filter users for registry refactor(registries): sync code with CE (#5200) * refactor(registry): add inspect handler under endpoints * refactor(endpoint): sync endpoint_registries_list * refactor(endpoints): sync registry_access * fix(db): rename migration functions * fix(registries): show accesses for admin * fix(kube): set token on transport * refactor(kube): move secret help to bottom * fix(kuberentes): remove shouldLog parameter * style(auth): add description of security.IsAdmin * feat(security): allow admin access to registry * feat(edge): connect to edge endpoint when creating client * style(portainer): change deprecation version * refactor(sidebar): hide manage * refactor(containers): revert changes * style(container): remove whitespace * fix(endpoint): add handler to registy on endpointService * refactor(image): use endpointService.registries * fix(kueb/namespaces): rename resource pool to namespace * fix(kube/namespace): move selected registries * fix(api/registries): hide accesses on registry creation Co-authored-by: LP B <xAt0mZ@users.noreply.github.com> refactor(api): remove code duplication after rebase fix(app/registries): replace last registry api usage by endpoint registry api fix(api/endpoints): update registry access policies on endpoint deletion (#5226) [EE-1027] fix(db): update db version * fix(dockerhub): fetch rate limits * fix(registry/tests): supply restricred context * fix(registries): show proget registry only when selected * fix(registry): create dockerhub registry * feat(db): move migrations to db 32 Co-authored-by: Chaim Lev-Ari <chiptus@gmail.com>
2021-07-14 09:15:21 +00:00
on-image-change="onImageNameChange()"
endpoint="endpoint"
is-admin="isAdmin"
check-rate-limits="formValues.alwaysPull"
set-validity="setPullImageValidity"
>
<!-- always-pull -->
<div class="form-group">
<div class="col-sm-12">
<label for="ownership" class="control-label text-left">
Always pull the image
<portainer-tooltip
position="bottom"
message="When enabled, Portainer will automatically try to pull the specified image before creating the container."
></portainer-tooltip>
</label>
<label class="switch" style="margin-left: 20px;">
<input type="checkbox" ng-model="formValues.alwaysPull" ng-disabled="!state.pullImageValidity" /><i></i>
</label>
</div>
</div>
<!-- !always-pull -->
</por-image-registry>
<!-- !image-and-registry -->
</div>
<div class="col-sm-12 form-section-title">
Network ports configuration
</div>
<!-- publish-exposed-ports -->
<div class="form-group">
<div class="col-sm-12">
<label class="control-label text-left">
Publish all exposed network ports to random host ports
<portainer-tooltip
position="bottom"
message="When enabled, Portainer will let Docker automatically map a random port on the host to each one defined in the image Dockerfile."
></portainer-tooltip>
</label>
<label class="switch" style="margin-left: 20px;"> <input type="checkbox" ng-model="config.HostConfig.PublishAllPorts" /><i></i> </label>
</div>
</div>
<!-- !publish-exposed-ports -->
<!-- port-mapping -->
<div class="form-group">
<div class="col-sm-12">
<label class="control-label text-left">
Manual network port publishing
<portainer-tooltip
position="bottom"
message="When a range of ports on the host and a single port on the container is specified, Docker will randomly choose a single available port in the defined range and forward that to the container port."
></portainer-tooltip>
</label>
<span class="label label-default interactive" style="margin-left: 10px;" ng-click="addPortBinding()">
<i class="fa fa-plus-circle" aria-hidden="true"></i> publish a new network port
</span>
</div>
<!-- port-mapping-input-list -->
<div class="col-sm-12 form-inline" style="margin-top: 10px;">
<div ng-repeat="portBinding in config.HostConfig.PortBindings" style="margin-top: 2px;">
<!-- host-port -->
<div class="input-group col-sm-4 input-group-sm">
<span class="input-group-addon">host</span>
<input type="text" class="form-control" ng-model="portBinding.hostPort" placeholder="e.g. 80, 80-88, ip:80 or ip:80-88 (optional)" />
</div>
<!-- !host-port -->
<span style="margin: 0 10px 0 10px;">
2018-03-13 05:36:53 +00:00
<i class="fa fa-long-arrow-alt-right" aria-hidden="true"></i>
</span>
<!-- container-port -->
<div class="input-group col-sm-4 input-group-sm">
<span class="input-group-addon">container</span>
<input type="text" class="form-control" ng-model="portBinding.containerPort" placeholder="e.g. 80 or 80-88" />
</div>
<!-- !container-port -->
<!-- protocol-actions -->
<div class="input-group col-sm-3 input-group-sm">
<div class="btn-group btn-group-sm">
<label class="btn btn-primary" ng-model="portBinding.protocol" uib-btn-radio="'tcp'">TCP</label>
<label class="btn btn-primary" ng-model="portBinding.protocol" uib-btn-radio="'udp'">UDP</label>
</div>
<button class="btn btn-sm btn-danger" type="button" ng-click="removePortBinding($index)">
<i class="fa fa-trash" aria-hidden="true"></i>
</button>
</div>
<!-- !protocol-actions -->
</div>
</div>
<!-- !port-mapping-input-list -->
</div>
<!-- !port-mapping -->
<div ng-if="applicationState.endpoint.mode.agentProxy && applicationState.endpoint.mode.provider === 'DOCKER_SWARM_MODE'">
2018-05-06 07:15:57 +00:00
<div class="col-sm-12 form-section-title">
Deployment
</div>
<!-- node-selection -->
<node-selector model="formValues.NodeName"> </node-selector>
2018-05-06 07:15:57 +00:00
<!-- !node-selection -->
</div>
<!-- access-control -->
<por-access-control-form form-data="formValues.AccessControlData" resource-control="fromContainer.ResourceControl" ng-if="fromContainer"></por-access-control-form>
<!-- !access-control -->
<!-- actions -->
<div class="col-sm-12 form-section-title">
Actions
</div>
<!-- autoremove -->
<div class="form-group">
<div class="col-sm-12">
<label for="ownership" class="control-label text-left">
Auto remove
<portainer-tooltip
position="bottom"
message="When enabled, Portainer will automatically remove the container when it exits. This is useful when you want to use the container only once."
></portainer-tooltip>
</label>
<label class="switch" style="margin-left: 20px;"> <input type="checkbox" ng-model="config.HostConfig.AutoRemove" /><i></i> </label>
</div>
</div>
<!-- !autoremove -->
<div class="form-group">
<div class="col-sm-12">
<button
type="button"
class="btn btn-primary btn-sm"
ng-disabled="state.actionInProgress || !formValues.RegistryModel.Image || (!formValues.RegistryModel.Registry && fromContainer)
|| (fromContainer.IsPortainer && fromContainer.Name === '/' + config.name)"
ng-click="create()"
button-spinner="state.actionInProgress"
>
<span ng-hide="state.actionInProgress">Deploy the container</span>
<span ng-show="state.actionInProgress">Deployment in progress...</span>
2017-11-12 19:27:28 +00:00
</button>
<span class="text-danger" ng-if="state.formValidationError" style="margin-left: 5px;">{{ state.formValidationError }}</span>
</div>
</div>
<!-- !actions -->
</form>
</rd-widget-body>
</rd-widget>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-xs-12">
<rd-widget>
<rd-widget-header icon="fa-cog" title-text="Advanced container settings"></rd-widget-header>
<rd-widget-body>
<ul class="nav nav-pills nav-justified">
<li class="active interactive"><a data-target="#command" data-toggle="tab">Command & logging</a></li>
<li class="interactive"><a data-target="#volumes" data-toggle="tab">Volumes</a></li>
<li class="interactive"><a data-target="#network" data-toggle="tab">Network</a></li>
<li class="interactive"><a data-target="#env" data-toggle="tab">Env</a></li>
<li class="interactive"><a data-target="#labels" data-toggle="tab">Labels</a></li>
<li class="interactive"><a data-target="#restart-policy" data-toggle="tab">Restart policy</a></li>
<li class="interactive"><a data-target="#runtime-resources" ng-click="refreshSlider()" data-toggle="tab">Runtime & Resources</a></li>
<li ng-if="areContainerCapabilitiesEnabled" class="interactive"><a data-target="#container-capabilities" data-toggle="tab">Capabilities</a></li>
</ul>
<!-- tab-content -->
<div class="tab-content">
<!-- tab-command -->
<div class="tab-pane active" id="command">
<form class="form-horizontal" style="margin-top: 15px;">
<!-- command-input -->
<div class="form-group">
<label for="container_command" class="col-sm-2 col-lg-1 control-label text-left">Command</label>
<div class="col-sm-9">
<div class="input-group">
<div class="input-group-btn">
<button class="btn btn-primary" ng-model="formValues.CmdMode" uib-btn-radio="'default'" style="margin-left: 0px;"> Default</button>
<button class="btn btn-primary" ng-model="formValues.CmdMode" uib-btn-radio="'override'">Override</button>
</div>
<input
type="text"
class="form-control"
ng-model="config.Cmd"
ng-disabled="formValues.CmdMode === 'default'"
id="container_command"
placeholder="e.g. '-logtostderr' '--housekeeping_interval=5s' or /usr/bin/nginx -t -c /mynginx.conf"
/>
</div>
</div>
</div>
<!-- !command-input -->
<!-- entrypoint-input -->
<div class="form-group">
<label for="container_entrypoint" class="col-sm-2 col-lg-1 control-label text-left">
Entrypoint
<portainer-tooltip
position="bottom"
message="When container entrypoint is entered as part of the Command field, set Entrypoint to Override mode and leave blank, else it will revert to default."
></portainer-tooltip>
</label>
<div class="col-sm-9">
<div class="input-group">
<div class="input-group-btn">
<label class="btn btn-primary" ng-model="formValues.EntrypointMode" uib-btn-radio="'default'" style="margin-left: 0px;"> Default</label>
<label class="btn btn-primary" ng-model="formValues.EntrypointMode" uib-btn-radio="'override'">Override</label>
</div>
<input
type="text"
class="form-control"
ng-model="config.Entrypoint"
ng-disabled="formValues.EntrypointMode === 'default'"
id="container_entrypoint"
placeholder="e.g. /bin/sh -c"
/>
</div>
</div>
</div>
<!-- !entrypoint-input -->
<!-- workdir-user-input -->
<div class="form-group">
<label for="container_workingdir" class="col-sm-2 col-lg-1 control-label text-left">Working Dir</label>
<div class="col-sm-4">
<input type="text" class="form-control" ng-model="config.WorkingDir" id="container_workingdir" placeholder="e.g. /myapp" />
</div>
<label for="container_user" class="col-sm-1 control-label text-left">User</label>
<div class="col-sm-4">
<input type="text" class="form-control" ng-model="config.User" id="container_user" placeholder="e.g. nginx" />
</div>
</div>
<!-- !workdir-user-input -->
<!-- console -->
<div class="form-group">
<label for="container_console" class="col-sm-2 col-lg-1 control-label text-left">Console</label>
<div class="col-sm-10 col-lg-11">
<div class="col-sm-4">
<label class="radio-inline">
<input type="radio" name="container_console" ng-model="formValues.Console" value="both" />
Interactive & TTY <span class="small text-muted">(-i -t)</span>
</label>
</div>
<div class="col-sm-4">
<label class="radio-inline">
<input type="radio" name="container_console" ng-model="formValues.Console" value="interactive" />
Interactive <span class="small text-muted">(-i)</span>
</label>
</div>
</div>
<div class="col-sm-offset-2 col-sm-10 col-lg-offset-1 col-lg-11">
<div class="col-sm-4">
<label class="radio-inline">
<input type="radio" name="container_console" ng-model="formValues.Console" value="tty" />
TTY <span class="small text-muted">(-t)</span>
</label>
</div>
<div class="col-sm-4">
<label class="radio-inline">
<input type="radio" name="container_console" ng-model="formValues.Console" value="none" />
None
</label>
</div>
</div>
</div>
<!-- !console -->
<div class="col-sm-12 form-section-title">
Logging
</div>
<!-- logging-driver -->
<div class="form-group">
<label for="log-driver" class="col-sm-2 col-lg-1 control-label text-left">Driver</label>
<div class="col-sm-4">
<select class="form-control" ng-model="formValues.LogDriverName" id="log-driver">
<option selected value="">Default logging driver</option>
<option ng-repeat="driver in availableLoggingDrivers" ng-value="driver">{{ driver }}</option>
<option value="none">none</option>
</select>
</div>
<div class="col-sm-5">
<p class="small text-muted">
Logging driver that will override the default docker daemon driver. Select Default logging driver if you don't want to override it. Supported logging drivers
can be found <a href="https://docs.docker.com/engine/admin/logging/overview/#supported-logging-drivers" target="_blank">in the Docker documentation</a>.
</p>
</div>
</div>
<!-- !logging-driver -->
<!-- logging-opts -->
<div class="form-group">
<div class="col-sm-12" style="margin-top: 5px;">
<label class="control-label text-left">
Options
<portainer-tooltip
position="top"
message="Add button is disabled unless a driver other than none or default is selected. Options are specific to the selected driver, refer to the driver documentation."
></portainer-tooltip>
</label>
<span
class="label label-default interactive"
style="margin-left: 10px;"
ng-click="!formValues.LogDriverName || formValues.LogDriverName === 'none' || addLogDriverOpt(formValues.LogDriverName)"
>
<i class="fa fa-plus-circle" aria-hidden="true"></i> add logging driver option
</span>
</div>
<!-- logging-opts-input-list -->
<div class="col-sm-12 form-inline" style="margin-top: 10px;">
<div ng-repeat="opt in formValues.LogDriverOpts" style="margin-top: 2px;">
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon">option</span>
<input type="text" class="form-control" ng-model="opt.name" placeholder="e.g. FOO" />
</div>
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon">value</span>
<input type="text" class="form-control" ng-model="opt.value" placeholder="e.g. bar" />
</div>
<button class="btn btn-sm btn-danger" type="button" ng-click="removeLogDriverOpt($index)">
<i class="fa fa-trash" aria-hidden="true"></i>
</button>
</div>
</div>
<!-- logging-opts-input-list -->
</div>
<!-- !logging-opts -->
</form>
</div>
<!-- !tab-command -->
<!-- tab-volume -->
<div class="tab-pane" id="volumes">
<form class="form-horizontal" style="margin-top: 15px;">
<!-- volumes -->
<div class="form-group">
<div class="col-sm-12" style="margin-top: 5px;">
<label class="control-label text-left">Volume mapping</label>
<span class="label label-default interactive" style="margin-left: 10px;" ng-click="addVolume()">
<i class="fa fa-plus-circle" aria-hidden="true"></i> map additional volume
</span>
</div>
<!-- volumes-input-list -->
<div class="form-inline" style="margin-top: 10px;">
<div ng-repeat="volume in formValues.Volumes">
<!-- volume-line1 -->
<div class="col-sm-12 form-inline" style="margin-top: 10px;">
<!-- container-path -->
<div class="input-group input-group-sm col-sm-6">
<span class="input-group-addon">container</span>
<input type="text" class="form-control" ng-model="volume.containerPath" placeholder="e.g. /path/in/container" />
</div>
<!-- !container-path -->
<!-- volume-type -->
<div class="input-group col-sm-5" style="margin-left: 5px;">
<div class="btn-group btn-group-sm" ng-if="allowBindMounts">
<label class="btn btn-primary" ng-model="volume.type" uib-btn-radio="'volume'" ng-click="volume.name = ''">Volume</label>
<label class="btn btn-primary" ng-model="volume.type" uib-btn-radio="'bind'" ng-click="volume.name = ''">Bind</label>
</div>
<button class="btn btn-sm btn-danger" type="button" ng-click="removeVolume($index)">
<i class="fa fa-trash" aria-hidden="true"></i>
</button>
</div>
<!-- !volume-type -->
</div>
<!-- !volume-line1 -->
<!-- volume-line2 -->
<div class="col-sm-12 form-inline" style="margin-top: 5px;">
2018-03-13 05:36:53 +00:00
<i class="fa fa-long-arrow-alt-right" aria-hidden="true"></i>
<!-- volume -->
<div class="input-group input-group-sm col-sm-6" ng-if="volume.type === 'volume'">
<span class="input-group-addon">volume</span>
<select class="form-control" ng-model="volume.name">
<option selected disabled hidden value="">Select a volume</option>
<option ng-repeat="vol in availableVolumes" ng-value="vol.Name">{{ vol.Name | truncate: 30 }} - {{ vol.Driver | truncate: 30 }}</option>
</select>
</div>
<!-- !volume -->
<!-- bind -->
<div class="input-group input-group-sm col-sm-6" ng-if="volume.type === 'bind'">
<span class="input-group-addon">host</span>
<input type="text" class="form-control" ng-model="volume.name" placeholder="e.g. /path/on/host" />
</div>
<!-- !bind -->
<!-- read-only -->
<div class="input-group input-group-sm col-sm-5" style="margin-left: 5px;">
<div class="btn-group btn-group-sm">
<label class="btn btn-primary" ng-model="volume.readOnly" uib-btn-radio="false">Writable</label>
<label class="btn btn-primary" ng-model="volume.readOnly" uib-btn-radio="true">Read-only</label>
</div>
</div>
<!-- !read-only -->
</div>
<!-- !volume-line2 -->
</div>
</div>
<!-- !volumes-input-list -->
</div>
</form>
<!-- !volumes -->
</div>
<!-- !tab-volume -->
<!-- tab-network -->
<div class="tab-pane" id="network">
<form class="form-horizontal" style="margin-top: 15px;">
<div class="form-group" ng-if="globalNetworkCount === 0 && applicationState.endpoint.mode.provider !== 'DOCKER_SWARM_MODE'">
<div class="col-sm-12">
<span class="small text-muted">You don't have any shared networks. Head over to the <a ui-sref="docker.networks">networks view</a> to create one.</span>
</div>
</div>
<!-- network-input -->
<div class="form-group">
<label for="container_network" class="col-sm-2 col-lg-1 control-label text-left">Network</label>
<div class="col-sm-9">
<select
class="form-control"
ng-options="net.Name as net.Name for net in availableNetworks"
ng-model="config.HostConfig.NetworkMode"
id="container_network"
ng-change="resetNetworkConfig()"
>
<option selected disabled hidden value="">Select a network</option>
</select>
</div>
</div>
<!-- !network-input -->
<!-- container-name-input -->
<div class="form-group" ng-if="config.HostConfig.NetworkMode == 'container'">
<label for="container_network_container" class="col-sm-2 col-lg-1 control-label text-left">Container</label>
<div class="col-sm-9">
<select ng-options="container|containername for container in runningContainers" class="form-control" ng-model="formValues.NetworkContainer">
<option selected disabled hidden value="">Select a container</option>
</select>
</div>
</div>
<!-- !container-name-input -->
<!-- hostname-input -->
<div class="form-group">
<label for="container_hostname" class="col-sm-2 col-lg-1 control-label text-left">Hostname</label>
<div class="col-sm-9">
<input type="text" class="form-control" ng-model="config.Hostname" id="container_hostname" placeholder="e.g. web01" />
</div>
</div>
<!-- !hostname-input -->
<!-- domainname-input -->
<div class="form-group">
<label for="container_domainname" class="col-sm-2 col-lg-1 control-label text-left">Domain Name</label>
<div class="col-sm-9">
<input type="text" class="form-control" ng-model="config.Domainname" id="container_domainname" placeholder="e.g. example.com" />
</div>
</div>
<!-- !domainname -->
<!-- mac-address-input -->
<div class="form-group">
<label for="container_macaddress" class="col-sm-2 col-lg-1 control-label text-left">Mac Address</label>
<div class="col-sm-9">
<input type="text" class="form-control" ng-model="formValues.MacAddress" id="container_macaddress" placeholder="e.g. 12-34-56-78-9a-bc" />
</div>
</div>
<!-- !mac-address-input -->
<!-- ipv4-input -->
<div class="form-group">
<label for="container_ipv4" class="col-sm-2 col-lg-1 control-label text-left">IPv4 Address</label>
<div class="col-sm-9">
<input type="text" class="form-control" ng-model="formValues.IPv4" id="container_ipv4" placeholder="e.g. 172.20.0.7" />
</div>
</div>
<!-- !ipv4-input -->
<!-- ipv6-input -->
<div class="form-group">
<label for="container_ipv6" class="col-sm-2 col-lg-1 control-label text-left">IPv6 Address</label>
<div class="col-sm-9">
<input type="text" class="form-control" ng-model="formValues.IPv6" id="container_ipv6" placeholder="e.g. a:b:c:d::1234" />
</div>
</div>
<!-- !ipv6-input -->
<!-- dns-primary-input -->
<div class="form-group">
<label for="container_dns_primary" class="col-sm-2 col-lg-1 control-label text-left">Primary DNS Server</label>
<div class="col-sm-9">
<input type="text" class="form-control" ng-model="formValues.DnsPrimary" id="container_dns_primary" placeholder="e.g. 1.1.1.1, 2606:4700:4700::1111" />
</div>
</div>
<!-- !dns-primary-input -->
<!-- dns-secondary-input -->
<div class="form-group">
<label for="container_dns_secondary" class="col-sm-2 col-lg-1 control-label text-left">Secondary DNS Server</label>
<div class="col-sm-9">
<input type="text" class="form-control" ng-model="formValues.DnsSecondary" id="container_dns_secondary" placeholder="e.g. 1.0.0.1, 2606:4700:4700::1001" />
</div>
</div>
<!-- !dns-secondary-input -->
<!-- extra-hosts-variables -->
<div class="form-group">
<div class="col-sm-12" style="margin-top: 5px;">
<label class="control-label text-left">Hosts file entries</label>
<span class="label label-default interactive" style="margin-left: 10px;" ng-click="addExtraHost()">
<i class="fa fa-plus-circle" aria-hidden="true"></i> add additional entry
</span>
</div>
<!-- extra-hosts-input-list -->
<div class="col-sm-12 form-inline" style="margin-top: 10px;">
<div ng-repeat="variable in formValues.ExtraHosts" style="margin-top: 2px;">
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon">value</span>
<input type="text" class="form-control" ng-model="variable.value" placeholder="e.g. host:IP" />
</div>
<button class="btn btn-sm btn-danger" type="button" ng-click="removeExtraHost($index)">
<i class="fa fa-trash" aria-hidden="true"></i>
</button>
</div>
</div>
<!-- !extra-hosts-input-list -->
</div>
<!-- !extra-hosts-variables -->
</form>
</div>
<!-- !tab-network -->
<!-- tab-labels -->
<div class="tab-pane" id="labels">
<form class="form-horizontal" style="margin-top: 15px;">
<!-- labels -->
<div class="form-group">
<div class="col-sm-12" style="margin-top: 5px;">
<label class="control-label text-left">Labels</label>
<span class="label label-default interactive" style="margin-left: 10px;" ng-click="addLabel()">
<i class="fa fa-plus-circle" aria-hidden="true"></i> add label
</span>
</div>
<!-- labels-input-list -->
<div class="col-sm-12 form-inline" style="margin-top: 10px;">
<div ng-repeat="label in formValues.Labels" style="margin-top: 2px;">
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon">name</span>
<input type="text" class="form-control" ng-model="label.name" placeholder="e.g. com.example.foo" />
</div>
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon">value</span>
<input type="text" class="form-control" ng-model="label.value" placeholder="e.g. bar" />
</div>
<button class="btn btn-sm btn-danger" type="button" ng-click="removeLabel($index)">
<i class="fa fa-trash" aria-hidden="true"></i>
</button>
</div>
</div>
<!-- !labels-input-list -->
</div>
<!-- !labels-->
</form>
</div>
<!-- !tab-labels -->
<!-- tab-env -->
<div class="tab-pane" id="env">
feat(UX): introduce new env variables UI (#4175) * feat(app): introduce new env vars ui feat(app): introduce new env vars ui feat(UX): WIP new env variables UI feat(UX): update button and placeholder feat(UX): mention .env file in message feat(UX): allow add/remove value & load correctly feat(UX): restrict filesize to 1MB feat(UX): vertical align error message feat(UX): fill UI from file & when switching modes feat(UX): strip un-needed newline character feat(UX): introduce component to other views feat(UX): fix title alignment feat(UX): only populate editor on mode switch when key exists feat(UX): prevent trimming of whitespace on values feat(UX): change editor to async feat(UX): add message describing use feat(UX): Refactor variable text to editorText refactor(app): rename env vars controller refactor(app): move env var explanation to parent refactor(app): order env var panels refactor(app): move simple env vars mode to component refactor(app): parse env vars refactor(app): move styles to css refactor(app): rename functions refactor(container): parse env vars refactor(env-vars): move utils to helper module refactor(env-vars): use util function for parse dot env file fix(env-vars): ignore comments refactor(services): use env vars utils refactor(env-vars): rename files refactor(env-panel): use utils style(stack): revert EnvContent to Env style(service): revert EnvContent to Env style(container): revert EnvContent to Env refactor(env-vars): support default value refactor(service): use new env var component refactor(env-var): use one way data flow refactor(containers): remove unused function * fix(env-vars): prevent using non .env files * refactor(env-vars): move env vars items to a component * feat(app): fixed env vars form validation in Stack * feat(services): disable env form submit if invalid * fix(app): show key pairs correctly * fix(env-var): use the same validation as with kubernetes * fix(env-vars): parse env var Co-authored-by: Chaim Lev-Ari <chiptus@gmail.com> Co-authored-by: Felix Han <felix.han@portainer.io>
2021-06-14 06:59:07 +00:00
<environment-variables-panel
ng-model="formValues.Env"
explanation="These values will be applied to the container when deployed"
on-change="(handleEnvVarChange)"
></environment-variables-panel>
</div>
feat(UX): introduce new env variables UI (#4175) * feat(app): introduce new env vars ui feat(app): introduce new env vars ui feat(UX): WIP new env variables UI feat(UX): update button and placeholder feat(UX): mention .env file in message feat(UX): allow add/remove value & load correctly feat(UX): restrict filesize to 1MB feat(UX): vertical align error message feat(UX): fill UI from file & when switching modes feat(UX): strip un-needed newline character feat(UX): introduce component to other views feat(UX): fix title alignment feat(UX): only populate editor on mode switch when key exists feat(UX): prevent trimming of whitespace on values feat(UX): change editor to async feat(UX): add message describing use feat(UX): Refactor variable text to editorText refactor(app): rename env vars controller refactor(app): move env var explanation to parent refactor(app): order env var panels refactor(app): move simple env vars mode to component refactor(app): parse env vars refactor(app): move styles to css refactor(app): rename functions refactor(container): parse env vars refactor(env-vars): move utils to helper module refactor(env-vars): use util function for parse dot env file fix(env-vars): ignore comments refactor(services): use env vars utils refactor(env-vars): rename files refactor(env-panel): use utils style(stack): revert EnvContent to Env style(service): revert EnvContent to Env style(container): revert EnvContent to Env refactor(env-vars): support default value refactor(service): use new env var component refactor(env-var): use one way data flow refactor(containers): remove unused function * fix(env-vars): prevent using non .env files * refactor(env-vars): move env vars items to a component * feat(app): fixed env vars form validation in Stack * feat(services): disable env form submit if invalid * fix(app): show key pairs correctly * fix(env-var): use the same validation as with kubernetes * fix(env-vars): parse env var Co-authored-by: Chaim Lev-Ari <chiptus@gmail.com> Co-authored-by: Felix Han <felix.han@portainer.io>
2021-06-14 06:59:07 +00:00
<!-- !tab-env -->
<!-- tab-restart-policy -->
<div class="tab-pane" id="restart-policy">
<form class="form-horizontal" style="margin-top: 15px;">
<div class="form-group">
<div class="col-sm-12">
<label class="control-label text-left">
Restart policy
</label>
<div class="btn-group btn-group-sm" style="margin-left: 20px;">
<label class="btn btn-primary" ng-model="config.HostConfig.RestartPolicy.Name" uib-btn-radio="'no'">
Never
</label>
<label class="btn btn-primary" ng-model="config.HostConfig.RestartPolicy.Name" uib-btn-radio="'always'">
Always
</label>
<label class="btn btn-primary" ng-model="config.HostConfig.RestartPolicy.Name" uib-btn-radio="'on-failure'">
On failure
</label>
<label class="btn btn-primary" ng-model="config.HostConfig.RestartPolicy.Name" uib-btn-radio="'unless-stopped'">
Unless stopped
</label>
</div>
</div>
</div>
</form>
</div>
<!-- !tab-restart-policy -->
<!-- tab-runtime-resources -->
<div class="tab-pane" id="runtime-resources">
<form class="form-horizontal" style="margin-top: 15px;">
<div class="col-sm-12 form-section-title">
Runtime
</div>
<!-- privileged-mode -->
<div class="form-group" ng-if="isAdmin || allowPrivilegedMode">
<div class="col-sm-12">
<label for="privileged_mode" class="control-label text-left">
Privileged mode
</label>
<label class="switch" style="margin-left: 20px;"> <input type="checkbox" name="privileged_mode" ng-model="config.HostConfig.Privileged" /><i></i> </label>
</div>
</div>
<!-- !privileged-mode -->
<!-- init -->
<div class="form-group" ng-if="applicationState.endpoint.apiVersion >= 1.37">
<div class="col-sm-12">
<label for="init" class="control-label text-left">
Init
</label>
<label class="switch" style="margin-left: 20px;"> <input type="checkbox" name="init" ng-model="config.HostConfig.Init" /><i></i> </label>
</div>
</div>
<!-- !init -->
<!-- runtimes -->
<div class="form-group">
<label for="container_runtime" class="col-sm-1 control-label text-left">Runtime</label>
<div class="col-sm-11">
<select class="form-control" ng-model="config.HostConfig.Runtime" id="container_runtime" ng-options="runtime for runtime in availableRuntimes">
<option selected value="">Default</option>
</select>
</div>
</div>
<!-- !runtimes -->
</form>
<form class="form-horizontal" style="margin-top: 15px;">
<!-- devices -->
<div ng-if="showDeviceMapping" class="form-group">
<div class="col-sm-12" style="margin-top: 5px;">
<label class="control-label text-left">Devices</label>
<span class="label label-default interactive" style="margin-left: 10px;" ng-click="addDevice()">
<i class="fa fa-plus-circle" aria-hidden="true"></i> add device
</span>
</div>
<!-- devices-input-list -->
<div class="col-sm-12 form-inline" style="margin-top: 10px;">
<div ng-repeat="device in config.HostConfig.Devices" style="margin-top: 2px;">
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon">host</span>
<input type="text" class="form-control" ng-model="device.pathOnHost" placeholder="e.g. /dev/tty0" />
</div>
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon">container</span>
<input type="text" class="form-control" ng-model="device.pathInContainer" placeholder="e.g. /dev/tty0" />
</div>
<button class="btn btn-sm btn-danger" type="button" ng-click="removeDevice($index)">
<i class="fa fa-trash" aria-hidden="true"></i>
</button>
</div>
</div>
<!-- !devices-input-list -->
</div>
<!-- !devices-->
<!-- sysctls -->
<div ng-if="showSysctls" class="form-group">
<div class="col-sm-12" style="margin-top: 5px;">
<label class="control-label text-left">Sysctls</label>
<span class="label label-default interactive" style="margin-left: 10px;" ng-click="addSysctl()">
<i class="fa fa-plus-circle" aria-hidden="true"></i> add sysctl
</span>
</div>
<!-- sysctls-input-list -->
<div class="col-sm-12 form-inline" style="margin-top: 10px;">
<div ng-repeat="sysctl in formValues.Sysctls" style="margin-top: 2px;">
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon">name</span>
<input type="text" class="form-control" ng-model="sysctl.name" placeholder="e.g. FOO" />
</div>
<div class="input-group col-sm-5 input-group-sm">
<span class="input-group-addon">value</span>
<input type="text" class="form-control" ng-model="sysctl.value" placeholder="e.g. bar" />
</div>
<button class="btn btn-sm btn-danger" type="button" ng-click="removeSysctl($index)">
<i class="fa fa-trash" aria-hidden="true"></i>
</button>
</div>
</div>
<!-- !sysctls-input-list -->
</div>
<!-- !sysctls -->
<div ng-class="{ 'edit-resources': state.mode == 'duplicate' }">
<div class="col-sm-12 form-section-title">
Resources
</div>
<!-- memory-reservation-input -->
<div class="form-group">
<label for="memory-reservation" class="col-sm-3 col-lg-2 control-label text-left mt-20">
Memory reservation
</label>
<div class="col-sm-3">
<slider
on-change="(handleResourceChange)"
model="formValues.MemoryReservation"
floor="0"
ceil="state.sliderMaxMemory"
step="256"
ng-if="state.sliderMaxMemory"
></slider>
</div>
<div class="col-sm-2">
<input type="number" min="0" class="form-control" ng-model="formValues.MemoryReservation" id="memory-reservation" />
</div>
<div class="col-sm-4">
<p class="small text-muted mt-7">
Memory soft limit (<b>MB</b>)
</p>
</div>
</div>
<!-- !memory-reservation-input -->
<!-- memory-limit-input -->
<div class="form-group">
<label for="memory-limit" class="col-sm-3 col-lg-2 control-label text-left mt-20">
Memory limit
</label>
<div class="col-sm-3">
<slider
on-change="(handleResourceChange)"
model="formValues.MemoryLimit"
floor="0"
ceil="state.sliderMaxMemory"
step="256"
ng-if="state.sliderMaxMemory"
></slider>
</div>
<div class="col-sm-2">
<input type="number" min="0" class="form-control" ng-model="formValues.MemoryLimit" id="memory-limit" />
</div>
<div class="col-sm-4">
<p class="small text-muted mt-7">
Memory limit (<b>MB</b>)
</p>
</div>
</div>
<!-- !memory-limit-input -->
<!-- cpu-limit-input -->
<div class="form-group">
<label for="cpu-limit" class="col-sm-3 col-lg-2 control-label text-left mt-20">
CPU limit
</label>
<div class="col-sm-5">
<slider
on-change="(handleResourceChange)"
model="formValues.CpuLimit"
floor="0"
ceil="state.sliderMaxCpu"
step="0.25"
precision="2"
ng-if="state.sliderMaxCpu"
></slider>
</div>
<div class="col-sm-4 mt-20">
<p class="small text-muted">
Maximum CPU usage
</p>
</div>
</div>
<!-- !cpu-limit-input -->
<!-- update-limit-btn -->
<div class="form-group" ng-if="state.mode == 'duplicate'">
<div class="col-sm-12">
<button
type="button"
class="btn btn-primary btn-sm"
ng-disabled="state.actionInProgress || !formValues.RegistryModel.Image || (!formValues.RegistryModel.Registry && fromContainer)"
ng-click="update()"
button-spinner="state.actionInProgress"
>
<span ng-hide="state.actionInProgress">Update Limits</span>
<span ng-show="state.actionInProgress">Update in progress...</span>
</button>
</div>
<div class="col-sm-12" ng-if="state.settingUnlimitedResources">
<p class="text-muted mr-4">
<i class="fa fa-exclamation-circle text-warning mt-10" aria-hidden="true"></i> Updating any resource value to unlimited' will redeploy this container.
</p>
</div>
</div>
<!-- !update-limit-btn -->
</div>
</form>
</div>
<!-- !tab-runtime-resources -->
<!-- tab-container-capabilities -->
<div class="tab-pane" id="container-capabilities">
<container-capabilities capabilities="formValues.capabilities"></container-capabilities>
</div>
<!-- !tab-container-capabilities -->
</div>
</rd-widget-body>
</rd-widget>
</div>
</div>