mirror of https://github.com/portainer/portainer
444 lines
23 KiB
HTML
444 lines
23 KiB
HTML
<rd-header>
|
|
<rd-header-title title="Create service"></rd-header-title>
|
|
<rd-header-content>
|
|
<a ui-sref="services">Services</a> > Add service
|
|
</rd-header-content>
|
|
</rd-header>
|
|
|
|
<div class="row">
|
|
<div class="col-lg-12 col-md-12 col-xs-12">
|
|
<rd-widget>
|
|
<rd-widget-body>
|
|
<form class="form-horizontal">
|
|
<!-- name-input -->
|
|
<div class="form-group">
|
|
<label for="service_name" class="col-sm-1 control-label text-left">Name</label>
|
|
<div class="col-sm-11">
|
|
<input type="text" class="form-control" ng-model="formValues.Name" id="service_name" placeholder="e.g. myService">
|
|
</div>
|
|
</div>
|
|
<!-- !name-input -->
|
|
<div class="col-sm-12 form-section-title">
|
|
Image configuration
|
|
</div>
|
|
<!-- image-and-registry-inputs -->
|
|
<div class="form-group">
|
|
<label for="service_image" class="col-sm-1 control-label text-left">Image</label>
|
|
<div class="col-sm-11 col-md-6">
|
|
<input type="text" class="form-control" ng-model="formValues.Image" id="service_image" placeholder="e.g. nginx:latest">
|
|
</div>
|
|
<label for="image_registry" class="col-sm-2 margin-sm-top control-label text-left">
|
|
Registry
|
|
<portainer-tooltip position="bottom" message="A registry to pull the image from. Leave empty to use the official Docker registry."></portainer-tooltip>
|
|
</label>
|
|
<div class="col-sm-10 col-md-3 margin-sm-top">
|
|
<input type="text" class="form-control" ng-model="formValues.Registry" id="image_registry" placeholder="e.g. myregistry.mydomain">
|
|
</div>
|
|
</div>
|
|
<!-- !image-and-registry-inputs -->
|
|
<div class="col-sm-12 form-section-title">
|
|
Scheduling
|
|
</div>
|
|
<!-- scheduling-mode -->
|
|
<div class="form-group">
|
|
<div class="col-sm-12">
|
|
<label class="control-label text-left">
|
|
Scheduling mode
|
|
</label>
|
|
<div class="btn-group btn-group-sm" style="margin-left: 20px;">
|
|
<label class="btn btn-primary" ng-model="formValues.Mode" uib-btn-radio="'global'">Global</label>
|
|
<label class="btn btn-primary" ng-model="formValues.Mode" uib-btn-radio="'replicated'">Replicated</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="form-group form-inline" ng-if="formValues.Mode === 'replicated'">
|
|
<div class="col-sm-12">
|
|
<label class="control-label text-left">
|
|
Replicas
|
|
</label>
|
|
<input type="number" class="form-control" ng-model="formValues.Replicas" id="replicas" placeholder="e.g. 3" style="margin-left: 20px;">
|
|
</div>
|
|
</div>
|
|
<!-- !scheduling-mode -->
|
|
<div class="col-sm-12 form-section-title">
|
|
Ports configuration
|
|
</div>
|
|
<!-- port-mapping -->
|
|
<div class="form-group">
|
|
<div class="col-sm-12" style="margin-top: 5px;">
|
|
<label class="control-label text-left">Port mapping</label>
|
|
<span class="label label-default interactive" style="margin-left: 10px;" ng-click="addPortBinding()">
|
|
<i class="fa fa-plus-circle" aria-hidden="true"></i> map additional port
|
|
</span>
|
|
</div>
|
|
<div class="col-sm-12 form-inline" style="margin-top: 10px;">
|
|
<div ng-repeat="portBinding in formValues.Ports" 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.PublishedPort" placeholder="e.g. 80 or 1.2.3.4:80 (optional)">
|
|
</div>
|
|
<!-- !host-port -->
|
|
<span style="margin: 0 10px 0 10px;">
|
|
<i class="fa fa-long-arrow-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.TargetPort" placeholder="e.g. 80">
|
|
</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 class="col-sm-12 form-section-title" ng-if="applicationState.application.authentication">
|
|
Access control
|
|
</div>
|
|
<!-- ownership -->
|
|
<div class="form-group" ng-if="applicationState.application.authentication">
|
|
<div class="col-sm-12">
|
|
<label for="ownership" class="control-label text-left">
|
|
Ownership
|
|
<portainer-tooltip position="bottom" message="When setting the ownership value to private, only you and the administrators will be able to see and manage this object. When choosing public, everybody will be able to access it."></portainer-tooltip>
|
|
</label>
|
|
<div class="btn-group btn-group-sm" style="margin-left: 20px;">
|
|
<label class="btn btn-primary" ng-model="formValues.Ownership" uib-btn-radio="'private'">
|
|
<i class="fa fa-eye-slash" aria-hidden="true"></i>
|
|
Private
|
|
</label>
|
|
<label class="btn btn-primary" ng-model="formValues.Ownership" uib-btn-radio="'public'">
|
|
<i class="fa fa-eye" aria-hidden="true"></i>
|
|
Public
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- !ownership -->
|
|
<!-- actions -->
|
|
<div class="col-sm-12 form-section-title">
|
|
Actions
|
|
</div>
|
|
<div class="form-group">
|
|
<div class="col-sm-12">
|
|
<button type="button" class="btn btn-primary btn-sm" ng-disabled="!formValues.Image" ng-click="create()">Create service</button>
|
|
<a type="button" class="btn btn-default btn-sm" ui-sref="services">Cancel</a>
|
|
<i id="createServiceSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px; display: none;"></i>
|
|
</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-body>
|
|
<ul class="nav nav-pills nav-justified">
|
|
<li class="active interactive"><a data-target="#command" data-toggle="tab">Command</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="#labels" data-toggle="tab">Labels</a></li>
|
|
<li class="interactive"><a data-target="#update-config" data-toggle="tab">Update config</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="service_command" class="col-sm-2 col-lg-1 control-label text-left">Command</label>
|
|
<div class="col-sm-9">
|
|
<input type="text" class="form-control" ng-model="formValues.Command" id="service_command" placeholder="e.g. /usr/bin/nginx -t -c /mynginx.conf">
|
|
</div>
|
|
</div>
|
|
<!-- !command-input -->
|
|
<!-- entrypoint-input -->
|
|
<div class="form-group">
|
|
<label for="service_entrypoint" class="col-sm-2 col-lg-1 control-label text-left">Entrypoint</label>
|
|
<div class="col-sm-9">
|
|
<input type="text" class="form-control" ng-model="formValues.EntryPoint" id="service_entrypoint" placeholder="e.g. /bin/sh -c">
|
|
</div>
|
|
</div>
|
|
<!-- !entrypoint-input -->
|
|
<!-- workdir-user-input -->
|
|
<div class="form-group">
|
|
<label for="service_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="formValues.WorkingDir" id="service_workingdir" placeholder="e.g. /myapp">
|
|
</div>
|
|
<label for="service_user" class="col-sm-1 control-label text-left">User</label>
|
|
<div class="col-sm-4">
|
|
<input type="text" class="form-control" ng-model="formValues.User" id="service_user" placeholder="e.g. nginx">
|
|
</div>
|
|
</div>
|
|
<!-- !workdir-user-input -->
|
|
<!-- environment-variables -->
|
|
<div class="form-group">
|
|
<div class="col-sm-12" style="margin-top: 5px;">
|
|
<label class="control-label text-left">Environment variables</label>
|
|
<span class="label label-default interactive" style="margin-left: 10px;" ng-click="addEnvironmentVariable()">
|
|
<i class="fa fa-plus-circle" aria-hidden="true"></i> add environment variable
|
|
</span>
|
|
</div>
|
|
<!-- environment-variable-input-list -->
|
|
<div class="col-sm-12 form-inline" style="margin-top: 10px;">
|
|
<div ng-repeat="variable in formValues.Env" 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="variable.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="variable.value" placeholder="e.g. bar">
|
|
</div>
|
|
<button class="btn btn-sm btn-danger" type="button" ng-click="removeEnvironmentVariable($index)">
|
|
<i class="fa fa-trash" aria-hidden="true"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<!-- !environment-variable-input-list -->
|
|
</div>
|
|
<!-- !environment-variables -->
|
|
</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="col-sm-12 form-inline" style="margin-top: 10px;">
|
|
<div ng-repeat="volume in formValues.Volumes">
|
|
<div class="col-sm-12" style="margin-top: 10px;">
|
|
<!-- volume-line1 -->
|
|
<div class="col-sm-12 form-inline">
|
|
<!-- 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.Target" 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">
|
|
<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;">
|
|
<i class="fa fa-long-arrow-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.Source">
|
|
<option selected disabled hidden value="">Select a volume</option>
|
|
<option ng-repeat="vol in availableVolumes" ng-value="vol.Name">{{ vol.Name|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.Source" 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>
|
|
</div>
|
|
<!-- !volumes-input-list -->
|
|
</div>
|
|
<!-- !volumes -->
|
|
</form>
|
|
</div>
|
|
<!-- !tab-volume -->
|
|
<!-- tab-network -->
|
|
<div class="tab-pane" id="network">
|
|
<form class="form-horizontal" style="margin-top: 15px;">
|
|
<!-- 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-model="formValues.Network">
|
|
<option selected disabled hidden value="">Select a network</option>
|
|
<option ng-repeat="net in availableNetworks" ng-value="net.Name">{{ net.Name }}</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-sm-2"></div>
|
|
</div>
|
|
<!-- !network-input -->
|
|
<!-- extra-networks -->
|
|
<div class="form-group">
|
|
<div class="col-sm-12" style="margin-top: 5px;">
|
|
<label class="control-label text-left">Extra networks</label>
|
|
<span class="label label-default interactive" style="margin-left: 10px;" ng-click="addExtraNetwork()">
|
|
<i class="fa fa-plus-circle" aria-hidden="true"></i> add extra network
|
|
</span>
|
|
</div>
|
|
<!-- network-input-list -->
|
|
<div class="col-sm-12 form-inline" style="margin-top: 10px;">
|
|
<div ng-repeat="network in formValues.ExtraNetworks" style="margin-top: 2px;">
|
|
<select class="form-control" ng-model="network.Name">
|
|
<option selected disabled hidden value="">Select a network</option>
|
|
<option ng-repeat="net in availableNetworks" ng-value="net.Name">{{ net.Name }}</option>
|
|
</select>
|
|
<button class="btn btn-sm btn-danger" type="button" ng-click="removeExtraNetwork($index)">
|
|
<i class="fa fa-trash" aria-hidden="true"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<!-- !network-input-list -->
|
|
</div>
|
|
<!-- !extra-networks -->
|
|
</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">Service 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 service 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-->
|
|
<!-- container-labels -->
|
|
<div class="form-group">
|
|
<div class="col-sm-12" style="margin-top: 5px;">
|
|
<label class="control-label text-left">Container labels</label>
|
|
<span class="label label-default interactive" style="margin-left: 10px;" ng-click="addContainerLabel()">
|
|
<i class="fa fa-plus-circle" aria-hidden="true"></i> add container label
|
|
</span>
|
|
</div>
|
|
<!-- container-labels-input-list -->
|
|
<div class="col-sm-12 form-inline" style="margin-top: 10px;">
|
|
<div ng-repeat="label in formValues.ContainerLabels" 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="removeContainerLabel($index)">
|
|
<i class="fa fa-trash" aria-hidden="true"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<!-- !container-labels-input-list -->
|
|
</div>
|
|
<!-- !container-labels-->
|
|
</form>
|
|
</div>
|
|
<!-- !tab-labels -->
|
|
<!-- tab-update-config -->
|
|
<div class="tab-pane" id="update-config">
|
|
<form class="form-horizontal" style="margin-top: 15px;">
|
|
<!-- parallelism-input -->
|
|
<div class="form-group">
|
|
<label for="parallelism" class="col-sm-2 col-lg-1 control-label text-left">Parallelism</label>
|
|
<div class="col-sm-2">
|
|
<input type="number" class="form-control" ng-model="formValues.Parallelism" id="parallelism" placeholder="e.g. 1">
|
|
</div>
|
|
<div class="col-sm-8">
|
|
<p class="small text-muted" style="margin-top: 10px;">
|
|
Maximum number of tasks to be updated simultaneously (0 to update all at once).
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<!-- !parallelism-input -->
|
|
<!-- delay-input -->
|
|
<div class="form-group">
|
|
<label for="update-delay" class="col-sm-2 col-lg-1 control-label text-left">Delay</label>
|
|
<div class="col-sm-2">
|
|
<input type="number" class="form-control" ng-model="formValues.UpdateDelay" id="update-delay" placeholder="e.g. 10">
|
|
</div>
|
|
<div class="col-sm-8">
|
|
<p class="small text-muted" style="margin-top: 10px;">
|
|
Amount of time between updates.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<!-- !delay-input -->
|
|
<!-- failureAction-input -->
|
|
<div class="form-group">
|
|
<div class="col-sm-12">
|
|
<label class="control-label text-left">Failure action</label>
|
|
<div class="btn-group btn-group-sm" style="margin-left: 20px;">
|
|
<label class="btn btn-primary" ng-model="formValues.FailureAction" uib-btn-radio="'continue'">Continue</label>
|
|
<label class="btn btn-primary" ng-model="formValues.FailureAction" uib-btn-radio="'pause'">Pause</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- !failureAction-input -->
|
|
</form>
|
|
</div>
|
|
<!-- !tab-update-config -->
|
|
</div>
|
|
</rd-widget-body>
|
|
</rd-widget>
|
|
</div>
|
|
</div>
|