This is an automated email from the ASF dual-hosted git repository.

marat pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-karavan.git


The following commit(s) were added to refs/heads/main by this push:
     new 9620c0dc Fix #1010
9620c0dc is described below

commit 9620c0dcad12f56d59fcc8c030e1ff2b962ad2c8
Author: Marat Gubaidullin <[email protected]>
AuthorDate: Mon Dec 4 17:17:46 2023 -0500

    Fix #1010
---
 .../camel/karavan/api/ContainerResource.java       | 124 ++++++++++++---------
 .../apache/camel/karavan/api/UsersResource.java    |   1 -
 .../org/apache/camel/karavan/code/CodeService.java |  55 ++++++++-
 .../camel/karavan/code/model/DockerCompose.java    |  19 ++++
 ...ockerCompose.java => DockerComposeNetwork.java} |  30 +++--
 .../karavan/code/model/DockerComposeService.java   |  20 ++++
 .../camel/karavan/docker/DockerEventListener.java  |  14 ++-
 .../camel/karavan/docker/DockerForGitea.java       |   2 +-
 .../camel/karavan/docker/DockerForInfinispan.java  |   2 +-
 .../camel/karavan/docker/DockerForKaravan.java     |  12 +-
 .../camel/karavan/docker/DockerForRegistry.java    |   2 +-
 .../apache/camel/karavan/docker/DockerService.java |  57 +++++++---
 .../apache/camel/karavan/docker/PullCallback.java  |  47 ++++++++
 .../camel/karavan/service/ProjectService.java      |  28 +----
 .../src/main/webui/src/api/KaravanApi.tsx          |  13 ++-
 .../src/main/webui/src/api/ProjectService.ts       |   4 +-
 .../src/main/webui/src/api/ProjectStore.ts         |  24 ++++
 .../src/containers/ContainerPage.css}              |  39 ++-----
 .../webui/src/containers/ContainerTableRow.tsx     |  13 ++-
 .../main/webui/src/containers/ContainersPage.tsx   |  44 ++------
 .../src/main/webui/src/project/ProjectPage.tsx     |  16 ++-
 .../main/webui/src/project/builder/BuildPanel.tsx  |   2 +-
 .../src/project/container/ContainerButtons.tsx     |  57 ++++++----
 .../webui/src/project/container/ContainerPanel.tsx |  12 +-
 .../src/project/container/ProjectContainerTab.tsx  |   6 +-
 .../src/main/webui/src/projects/ProjectsPage.tsx   |   4 +-
 .../main/webui/src/projects/ProjectsTableRow.tsx   |  35 ++----
 .../main/webui/src/services/ServicesTableRow.tsx   |   6 +-
 28 files changed, 419 insertions(+), 269 deletions(-)

diff --git 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/ContainerResource.java
 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/ContainerResource.java
index 23e0d8e8..8effafe0 100644
--- 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/ContainerResource.java
+++ 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/ContainerResource.java
@@ -79,67 +79,81 @@ public class ContainerResource {
     @POST
     @Produces(MediaType.APPLICATION_JSON)
     @Consumes(MediaType.APPLICATION_JSON)
-    @Path("/{env}/{type}/{name}")
-    public Response manageContainer(@PathParam("env") String env, 
@PathParam("type") String type, @PathParam("name") String name, JsonObject 
command) throws Exception {
-        if (infinispanService.isReady()) {
-            if (ConfigService.inKubernetes()) {
-                if (command.getString("command").equalsIgnoreCase("delete")) {
-                    kubernetesService.deletePod(name);
-                    return Response.ok().build();
-                }
-            } else {
-                // set container statuses
-                setContainerStatusTransit(name, type);
-                // exec docker commands
-                if (command.containsKey("command")) {
-                    if (command.getString("command").equalsIgnoreCase("run")) {
-                        if (Objects.equals(type, 
ContainerStatus.ContainerType.devservice.name())) {
-                            String code = projectService.getDevServiceCode();
-                            DockerComposeService dockerComposeService = 
DockerComposeConverter.fromCode(code, name);
-                            if (dockerComposeService != null) {
-                                Map<String,String> labels = new HashMap<>();
-                                labels.put(LABEL_TYPE, 
ContainerStatus.ContainerType.devservice.name());
-                                labels.put(LABEL_CAMEL_RUNTIME, 
CamelRuntime.CAMEL_MAIN.getValue());
-                                labels.put(LABEL_PROJECT_ID, name);
-                                
dockerService.createContainerFromCompose(dockerComposeService, labels);
-                                
dockerService.runContainer(dockerComposeService.getContainer_name());
-                            }
-                        } else if (Objects.equals(type, 
ContainerStatus.ContainerType.project.name())) {
-                            DockerComposeService dockerComposeService = 
projectService.getProjectDockerComposeService(name);
-                            if (dockerComposeService != null) {
-                                Map<String,String> labels = new HashMap<>();
-                                labels.put(LABEL_TYPE, 
ContainerStatus.ContainerType.project.name());
-                                labels.put(LABEL_CAMEL_RUNTIME, 
CamelRuntime.CAMEL_MAIN.getValue());
-                                labels.put(LABEL_PROJECT_ID, name);
-                                
dockerService.createContainerFromCompose(dockerComposeService, labels);
-                                
dockerService.runContainer(dockerComposeService.getContainer_name());
-                            }
-                        } else if (Objects.equals(type, 
ContainerStatus.ContainerType.devmode.name())) {
-//                        TODO: merge with DevMode service
-//                        dockerForKaravan.createDevmodeContainer(name, "");
-//                        dockerService.runContainer(name);
-                        }
-                        return Response.ok().build();
-                    } else if 
(command.getString("command").equalsIgnoreCase("stop")) {
-                        dockerService.stopContainer(name);
-                        return Response.ok().build();
-                    } else if 
(command.getString("command").equalsIgnoreCase("pause")) {
-                        dockerService.pauseContainer(name);
+    @Path("/{projectId}/{type}/{name}")
+    public Response manageContainer(@PathParam("projectId") String projectId, 
@PathParam("type") String type, @PathParam("name") String name, JsonObject 
command) {
+        try {
+            if (infinispanService.isReady()) {
+                if (ConfigService.inKubernetes()) {
+                    if 
(command.getString("command").equalsIgnoreCase("delete")) {
+                        kubernetesService.deletePod(name);
                         return Response.ok().build();
-                    } else if 
(command.getString("command").equalsIgnoreCase("delete")) {
-                        dockerService.deleteContainer(name);
+                    }
+                } else {
+                    // set container statuses
+                    setContainerStatusTransit(projectId, name, type);
+                    // exec docker commands
+                    if (command.containsKey("command")) {
+                        if 
(command.getString("command").equalsIgnoreCase("deploy")) {
+                            deployContainer(projectId, type, command);
+                        } else if 
(command.getString("command").equalsIgnoreCase("run")) {
+                            dockerService.runContainer(name);
+                        } else if 
(command.getString("command").equalsIgnoreCase("stop")) {
+                            dockerService.stopContainer(name);
+                        } else if 
(command.getString("command").equalsIgnoreCase("pause")) {
+                            dockerService.pauseContainer(name);
+                        } else if 
(command.getString("command").equalsIgnoreCase("delete")) {
+                            dockerService.deleteContainer(name);
+                        }
                         return Response.ok().build();
                     }
                 }
             }
+            return Response.notModified().build();
+        } catch (Exception e) {
+            return Response.serverError().entity(e.getMessage()).build();
         }
-        return Response.notModified().build();
     }
 
-    private void setContainerStatusTransit(String name, String type){
-        ContainerStatus status = infinispanService.getContainerStatus(name, 
environment, name);
+    private void deployContainer(String projectId, String type, JsonObject 
command) throws InterruptedException {
+        if (Objects.equals(type, 
ContainerStatus.ContainerType.devservice.name())) {
+            String code = projectService.getDevServiceCode();
+            DockerComposeService dockerComposeService = 
DockerComposeConverter.fromCode(code, projectId);
+            if (dockerComposeService != null) {
+                Map<String, String> labels = new HashMap<>();
+                labels.put(LABEL_TYPE, 
ContainerStatus.ContainerType.devservice.name());
+                labels.put(LABEL_CAMEL_RUNTIME, 
CamelRuntime.CAMEL_MAIN.getValue());
+                labels.put(LABEL_PROJECT_ID, projectId);
+                dockerService.createContainerFromCompose(dockerComposeService, 
labels, needPull(command));
+                
dockerService.runContainer(dockerComposeService.getContainer_name());
+            }
+        } else if (Objects.equals(type, 
ContainerStatus.ContainerType.project.name())) {
+            DockerComposeService dockerComposeService = 
projectService.getProjectDockerComposeService(projectId);
+            if (dockerComposeService != null) {
+                Map<String, String> labels = new HashMap<>();
+                labels.put(LABEL_TYPE, 
ContainerStatus.ContainerType.project.name());
+                labels.put(LABEL_CAMEL_RUNTIME, 
CamelRuntime.CAMEL_MAIN.getValue());
+                labels.put(LABEL_PROJECT_ID, projectId);
+                dockerService.createContainerFromCompose(dockerComposeService, 
labels, needPull(command));
+                
dockerService.runContainer(dockerComposeService.getContainer_name());
+            }
+        } else if (Objects.equals(type, 
ContainerStatus.ContainerType.devmode.name())) {
+//                        TODO: merge with DevMode service
+//                        dockerForKaravan.createDevmodeContainer(name, "");
+//                        dockerService.runContainer(name);
+        }
+    }
+
+    private boolean needPull(JsonObject command) {
+        if (command != null && command.containsKey("pullImage")) {
+            return command.getBoolean("pullImage");
+        }
+        return false;
+    }
+
+    private void setContainerStatusTransit(String projectId, String name, 
String type) {
+        ContainerStatus status = 
infinispanService.getContainerStatus(projectId, environment, name);
         if (status == null) {
-            status = ContainerStatus.createByType(name, environment, 
ContainerStatus.ContainerType.valueOf(type));
+            status = ContainerStatus.createByType(projectId, environment, 
ContainerStatus.ContainerType.valueOf(type));
         }
         status.setInTransit(true);
         eventBus.send(CONTAINER_STATUS, JsonObject.mapFrom(status));
@@ -167,11 +181,11 @@ public class ContainerResource {
     @DELETE
     @Produces(MediaType.APPLICATION_JSON)
     @Consumes(MediaType.APPLICATION_JSON)
-    @Path("/{env}/{type}/{name}")
-    public Response deleteContainer(@PathParam("env") String env, 
@PathParam("type") String type, @PathParam("name") String name) {
+    @Path("/{projectId}/{type}/{name}")
+    public Response deleteContainer(@PathParam("projectId") String projectId, 
@PathParam("type") String type, @PathParam("name") String name) {
         if (infinispanService.isReady()) {
             // set container statuses
-            setContainerStatusTransit(name, type);
+            setContainerStatusTransit(projectId, name, type);
             try {
                 if (ConfigService.inKubernetes()) {
                     kubernetesService.deletePod(name);
diff --git 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/UsersResource.java
 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/UsersResource.java
index 83bd9469..fbf6e61e 100644
--- 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/UsersResource.java
+++ 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/UsersResource.java
@@ -17,7 +17,6 @@
 
 package org.apache.camel.karavan.api;
 
-import io.quarkus.oidc.UserInfo;
 import io.quarkus.security.identity.SecurityIdentity;
 import jakarta.inject.Inject;
 import jakarta.ws.rs.GET;
diff --git 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/code/CodeService.java
 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/code/CodeService.java
index 18e44f57..cab3a77e 100644
--- 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/code/CodeService.java
+++ 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/code/CodeService.java
@@ -61,6 +61,7 @@ public class CodeService {
     public static final String PROJECT_JKUBE_EXTENSION = ".jkube.yaml";
     public static final String PROJECT_DEPLOYMENT_JKUBE_FILENAME = 
"deployment" + PROJECT_JKUBE_EXTENSION;
     private static final String SNIPPETS_PATH = "/snippets/";
+    private static final String DATA_FOLDER = System.getProperty("user.dir") + 
File.separator + "data";
     private static final int INTERNAL_PORT = 8080;
 
     @Inject
@@ -257,7 +258,7 @@ public class CodeService {
                 .data("projectId", project.getProjectId())
                 .data("projectPort", port)
                 .data("projectImage", project.getProjectId());
-        String code =  instance.render();
+        String code = instance.render();
         return new ProjectFile(PROJECT_COMPOSE_FILENAME, code, 
project.getProjectId(), Instant.now().toEpochMilli());
     }
 
@@ -293,11 +294,63 @@ public class CodeService {
         return port.orElse(null);
     }
 
+    public Integer getProjectPort(String projectId) {
+        ProjectFile composeFile = infinispanService.getProjectFile(projectId, 
PROJECT_COMPOSE_FILENAME);
+        return getProjectPort(composeFile);
+    }
+
 
     public DockerComposeService getInternalDockerComposeService (String name) {
         String composeText = getResourceFile("/services/internal.yaml");
         return DockerComposeConverter.fromCode(composeText, name);
     }
 
+    public DockerComposeService getDockerComposeService(String projectId) {
+        ProjectFile compose = infinispanService.getProjectFile(projectId, 
PROJECT_COMPOSE_FILENAME);
+        if (compose != null) {
+            return DockerComposeConverter.fromCode(compose.getCode(), 
projectId);
+        }
+        return null;
+    }
+
+    public void updateDockerComposeImage(String projectId, String imageName) {
+        ProjectFile compose = infinispanService.getProjectFile(projectId, 
PROJECT_COMPOSE_FILENAME);
+        if (compose != null) {
+            DockerComposeService service = 
DockerComposeConverter.fromCode(compose.getCode(), projectId);
+            service.setImage(imageName);
+            String code = DockerComposeConverter.toCode(service);
+            compose.setCode(code);
+            infinispanService.saveProjectFile(compose);
+        }
+    }
+
+    public List<String> getComposeEnvironmentVariables(String projectId) {
+        DockerComposeService compose = getDockerComposeService(projectId);
+        return getComposeEnvironmentVariables(compose);
+    }
+
+    public List<String> getComposeEnvironmentVariables(DockerComposeService 
compose) {
+        List<String> vars = new ArrayList<>();
+        if (compose.getEnv_file() != null && !compose.getEnv_file().isEmpty()) 
{
+            compose.getEnv_file().forEach(name -> {
+                String file = getDataFile(name);
+                vars.addAll(getEnvironmentVariablesFromString(file));
+            });
+        }
+        return vars;
+    }
+
+    private List<String> getEnvironmentVariablesFromString(String file) {
+        List<String> vars = new ArrayList<>();
+        if (file != null) {
+            vars = file.lines().collect(Collectors.toList());
+        }
+        return vars;
+    }
+
+    public String getDataFile(String name) {
+        String fileName = DATA_FOLDER + File.separator + name;
+        return vertx.fileSystem().readFileBlocking(fileName).toString();
+    }
 
 }
diff --git 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/code/model/DockerCompose.java
 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/code/model/DockerCompose.java
index 856df6c5..d75ba9ec 100644
--- 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/code/model/DockerCompose.java
+++ 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/code/model/DockerCompose.java
@@ -17,11 +17,14 @@
 
 package org.apache.camel.karavan.code.model;
 
+
 import java.util.HashMap;
 import java.util.Map;
 
 public class DockerCompose {
+    private String version;
     private Map<String, DockerComposeService> services;
+    private Map<String, DockerComposeNetwork> networks;
 
     public DockerCompose() {
     }
@@ -43,4 +46,20 @@ public class DockerCompose {
     public void setServices(Map<String, DockerComposeService> services) {
         this.services = services;
     }
+
+    public String getVersion() {
+        return version;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
+    public Map<String, DockerComposeNetwork> getNetworks() {
+        return networks;
+    }
+
+    public void setNetworks(Map<String, DockerComposeNetwork> networks) {
+        this.networks = networks;
+    }
 }
diff --git 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/code/model/DockerCompose.java
 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/code/model/DockerComposeNetwork.java
similarity index 56%
copy from 
karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/code/model/DockerCompose.java
copy to 
karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/code/model/DockerComposeNetwork.java
index 856df6c5..fb682af3 100644
--- 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/code/model/DockerCompose.java
+++ 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/code/model/DockerComposeNetwork.java
@@ -17,30 +17,28 @@
 
 package org.apache.camel.karavan.code.model;
 
-import java.util.HashMap;
-import java.util.Map;
 
-public class DockerCompose {
-    private Map<String, DockerComposeService> services;
+public class DockerComposeNetwork {
 
-    public DockerCompose() {
+    private String name;
+    private Boolean external;
+
+    public DockerComposeNetwork() {
     }
 
-    public DockerCompose(Map<String, DockerComposeService> services) {
-        this.services = services;
+    public String getName() {
+        return name;
     }
 
-    public static DockerCompose create(DockerComposeService service) {
-        Map<String, DockerComposeService> map = new HashMap<>();
-        map.put(service.getContainer_name(), service);
-        return new DockerCompose(map);
+    public void setName(String name) {
+        this.name = name;
     }
 
-    public Map<String, DockerComposeService> getServices() {
-        return services;
+    public Boolean getExternal() {
+        return external;
     }
 
-    public void setServices(Map<String, DockerComposeService> services) {
-        this.services = services;
+    public void setExternal(Boolean external) {
+        this.external = external;
     }
-}
+}
\ No newline at end of file
diff --git 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/code/model/DockerComposeService.java
 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/code/model/DockerComposeService.java
index 0370faae..a9df8b33 100644
--- 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/code/model/DockerComposeService.java
+++ 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/code/model/DockerComposeService.java
@@ -31,6 +31,8 @@ public class DockerComposeService {
     private List<String> ports;
     private List<String> expose;
     private List<String> depends_on;
+    private List<String> env_file;
+    private List<String> networks;
     private Map<String,String> environment;
     private DockerComposeHealthCheck healthcheck;
 
@@ -124,6 +126,22 @@ public class DockerComposeService {
         this.healthcheck = healthcheck;
     }
 
+    public List<String> getEnv_file() {
+        return env_file;
+    }
+
+    public void setEnv_file(List<String> env_file) {
+        this.env_file = env_file;
+    }
+
+    public List<String> getNetworks() {
+        return networks;
+    }
+
+    public void setNetworks(List<String> networks) {
+        this.networks = networks;
+    }
+
     @Override
     public String toString() {
         return "DockerComposeService {" +
@@ -131,6 +149,8 @@ public class DockerComposeService {
                 ", image='" + image + '\'' +
                 ", restart='" + restart + '\'' +
                 ", ports=" + ports +
+                ", env_file=" + env_file +
+                ", networks=" + networks +
                 ", expose=" + expose +
                 ", depends_on='" + depends_on + '\'' +
                 ", environment=" + environment +
diff --git 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerEventListener.java
 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerEventListener.java
index d3ed22a3..31e589e3 100644
--- 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerEventListener.java
+++ 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerEventListener.java
@@ -25,6 +25,7 @@ import jakarta.enterprise.context.ApplicationScoped;
 import jakarta.inject.Inject;
 import org.apache.camel.karavan.infinispan.InfinispanService;
 import org.apache.camel.karavan.infinispan.model.ContainerStatus;
+import org.apache.camel.karavan.registry.RegistryService;
 import org.jboss.logging.Logger;
 
 import java.io.Closeable;
@@ -40,7 +41,7 @@ public class DockerEventListener implements 
ResultCallback<Event> {
     DockerService dockerService;
 
     @Inject
-    DockerForKaravan dockerForKaravan;
+    RegistryService registryService;
 
     @Inject
     InfinispanService infinispanService;
@@ -72,11 +73,16 @@ public class DockerEventListener implements 
ResultCallback<Event> {
                     && Objects.equals(container.getLabels().get(LABEL_TYPE), 
ContainerStatus.ContainerType.build.name())) {
                 String tag = container.getLabels().get(LABEL_TAG);
                 String projectId = container.getLabels().get(LABEL_PROJECT_ID);
-                dockerForKaravan.syncImage(projectId, tag);
+                syncImage(projectId, tag);
             }
         }
     }
 
+    private void syncImage(String projectId, String tag) throws 
InterruptedException {
+        String image = registryService.getRegistryWithGroupForSync() + "/" + 
projectId + ":" + tag;
+        dockerService.pullImage(image, true);
+    }
+
     @Override
     public void onError(Throwable throwable) {
         LOGGER.error(throwable.getMessage());
@@ -91,6 +97,4 @@ public class DockerEventListener implements 
ResultCallback<Event> {
     public void close() throws IOException {
         LOGGER.info("DockerEventListener close");
     }
-
-
-}
+}
\ No newline at end of file
diff --git 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForGitea.java
 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForGitea.java
index 1e640240..7fec9e0d 100644
--- 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForGitea.java
+++ 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForGitea.java
@@ -46,7 +46,7 @@ public class DockerForGitea {
         try {
             LOGGER.info("Gitea container is starting...");
             var compose = 
codeService.getInternalDockerComposeService(GITEA_CONTAINER_NAME);
-            Container c = dockerService.createContainerFromCompose(compose, 
ContainerStatus.ContainerType.internal);
+            Container c = dockerService.createContainerFromCompose(compose, 
ContainerStatus.ContainerType.internal, false);
             dockerService.runContainer(GITEA_CONTAINER_NAME);
             LOGGER.info("Gitea container is started");
         } catch (Exception e) {
diff --git 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForInfinispan.java
 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForInfinispan.java
index 29874102..5c594513 100644
--- 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForInfinispan.java
+++ 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForInfinispan.java
@@ -47,7 +47,7 @@ public class DockerForInfinispan {
             var compose = 
codeService.getInternalDockerComposeService(INFINISPAN_CONTAINER_NAME);
             compose.addEnvironment("USER", infinispanUsername);
             compose.addEnvironment("PASS", infinispanPassword);
-            dockerService.createContainerFromCompose(compose, 
ContainerStatus.ContainerType.internal);
+            dockerService.createContainerFromCompose(compose, 
ContainerStatus.ContainerType.internal, false);
             dockerService.runContainer(INFINISPAN_CONTAINER_NAME);
             LOGGER.info("Infinispan is started");
         } catch (Exception e) {
diff --git 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForKaravan.java
 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForKaravan.java
index 54c31973..9c757097 100644
--- 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForKaravan.java
+++ 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForKaravan.java
@@ -23,7 +23,6 @@ import jakarta.enterprise.context.ApplicationScoped;
 import jakarta.inject.Inject;
 import org.apache.camel.karavan.infinispan.model.ContainerStatus;
 import org.apache.camel.karavan.infinispan.model.Project;
-import org.apache.camel.karavan.registry.RegistryService;
 import org.eclipse.microprofile.config.inject.ConfigProperty;
 import org.jboss.logging.Logger;
 
@@ -47,9 +46,6 @@ public class DockerForKaravan {
     @Inject
     DockerService dockerService;
 
-    @Inject
-    RegistryService registryService;
-
     public void runProjectInDevMode(String projectId, String jBangOptions, 
Map<Integer, Integer> ports,
                                     Map<String, String> files) throws 
Exception {
         Map<String, String> volumes = getMavenVolumes();
@@ -74,7 +70,7 @@ public class DockerForKaravan {
                         LABEL_PROJECT_ID, projectId,
                         LABEL_CAMEL_RUNTIME, CamelRuntime.CAMEL_MAIN.getValue()
                 ),
-                volumes, null, RestartPolicy.noRestart());
+                volumes, null, RestartPolicy.noRestart(), false);
 
     }
 
@@ -97,15 +93,11 @@ public class DockerForKaravan {
                         LABEL_PROJECT_ID, project.getProjectId(),
                         LABEL_TAG, tag
                 ),
-                volumes, null,RestartPolicy.noRestart(), 
"/karavan/builder/build.sh");
+                volumes, null,RestartPolicy.noRestart(), false, 
"/karavan/builder/build.sh");
     }
 
     private Map<String,String> getMavenVolumes(){
         return mavenCache.map(s -> Map.of(s, 
"/karavan/.m2")).orElseGet(Map::of);
     }
 
-    public void syncImage(String projectId, String tag) throws 
InterruptedException {
-        String image = registryService.getRegistryWithGroupForSync() + "/" + 
projectId + ":" + tag;
-        dockerService.pullImage(image);
-    }
 }
diff --git 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForRegistry.java
 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForRegistry.java
index 0bd9c6d0..4638fe82 100644
--- 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForRegistry.java
+++ 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerForRegistry.java
@@ -39,7 +39,7 @@ public class DockerForRegistry {
         try {
             LOGGER.info("Registry is starting...");
             var compose = 
codeService.getInternalDockerComposeService(REGISTRY_CONTAINER_NAME);
-            dockerService.createContainerFromCompose(compose, 
ContainerStatus.ContainerType.internal);
+            dockerService.createContainerFromCompose(compose, 
ContainerStatus.ContainerType.internal, false);
             dockerService.runContainer(REGISTRY_CONTAINER_NAME);
             LOGGER.info("Registry is started");
         } catch (Exception e) {
diff --git 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java
 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java
index 00389096..b87e945d 100644
--- 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java
+++ 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java
@@ -62,6 +62,15 @@ public class DockerService extends DockerServiceUtils {
     @ConfigProperty(name = "karavan.docker.network")
     String networkName;
 
+    @ConfigProperty(name = "karavan.image-registry")
+    String registry;
+    @ConfigProperty(name = "karavan.image-group")
+    String group;
+    @ConfigProperty(name = "karavan.image-registry-username")
+    Optional<String> username;
+    @ConfigProperty(name = "karavan.image-registry-password")
+    Optional<String> password;
+
     @Inject
     DockerEventListener dockerEventListener;
 
@@ -154,25 +163,31 @@ public class DockerService extends DockerServiceUtils {
         return stats;
     }
 
-    public Container createContainerFromCompose(DockerComposeService compose, 
ContainerStatus.ContainerType type, String... command) throws 
InterruptedException {
-        return createContainerFromCompose(compose, type, Map.of(), command);
+    public Container createContainerFromCompose(DockerComposeService compose, 
ContainerStatus.ContainerType type, Boolean pull, String... command) throws 
InterruptedException {
+        return createContainerFromCompose(compose, type, Map.of(), pull, 
command);
     }
 
-    public Container createContainerFromCompose(DockerComposeService compose, 
ContainerStatus.ContainerType type, Map<String, String> volumes, String... 
command) throws InterruptedException {
+    public Container createContainerFromCompose(DockerComposeService compose, 
ContainerStatus.ContainerType type, Map<String, String> volumes, Boolean 
pullAlways, String... command) throws InterruptedException {
         Map<String,String> labels = new HashMap<>();
         labels.put(LABEL_TYPE, type.name());
-        return createContainerFromCompose(compose, labels, volumes, command);
+        return createContainerFromCompose(compose, labels, volumes, 
pullAlways, command);
     }
 
-    public Container createContainerFromCompose(DockerComposeService compose, 
Map<String, String> labels, String... command) throws InterruptedException {
-        return createContainerFromCompose(compose, labels, Map.of(), command);
+    public Container createContainerFromCompose(DockerComposeService compose, 
Map<String, String> labels, Boolean pullAlways, String... command) throws 
InterruptedException {
+        return createContainerFromCompose(compose, labels, Map.of(), 
pullAlways, command);
     }
 
-    public Container createContainerFromCompose(DockerComposeService compose, 
Map<String, String> labels, Map<String, String> volumes, String... command) 
throws InterruptedException {
+    public Container createContainerFromCompose(DockerComposeService compose, 
Map<String, String> labels, Map<String, String> volumes, Boolean pullAlways, 
String... command) throws InterruptedException {
         List<Container> containers = 
findContainer(compose.getContainer_name());
         if (containers.isEmpty()) {
             HealthCheck healthCheck = getHealthCheck(compose.getHealthcheck());
-            List<String> env = compose.getEnvironment() != null ? 
compose.getEnvironmentList() : List.of();
+
+            List<String> env = new ArrayList<>();
+            if (compose.getEnv_file() != null) {
+                
env.addAll(codeService.getComposeEnvironmentVariables(compose));
+            } else {
+                env.addAll(compose.getEnvironmentList());
+            }
 
             LOGGER.infof("Compose Service started for %s in network:%s", 
compose.getContainer_name(), networkName);
 
@@ -184,7 +199,7 @@ public class DockerService extends DockerServiceUtils {
             }
 
             return createContainer(compose.getContainer_name(), 
compose.getImage(),
-                    env, compose.getPortsMap(), healthCheck, labels, volumes, 
networkName, restartPolicy, command);
+                    env, compose.getPortsMap(), healthCheck, labels, volumes, 
networkName, restartPolicy, pullAlways, command);
 
         } else {
             LOGGER.info("Compose Service already exists: " + 
containers.get(0).getId());
@@ -200,10 +215,11 @@ public class DockerService extends DockerServiceUtils {
     public Container createContainer(String name, String image, List<String> 
env, Map<Integer, Integer> ports,
                                      HealthCheck healthCheck, Map<String, 
String> labels,
                                      Map<String, String> volumes, String 
network, RestartPolicy restartPolicy,
+                                     boolean pullAlways,
                                      String... command) throws 
InterruptedException {
         List<Container> containers = findContainer(name);
         if (containers.isEmpty()) {
-            pullImage(image);
+            pullImage(image, pullAlways);
 
             CreateContainerCmd createContainerCmd = 
getDockerClient().createContainerCmd(image)
                     
.withName(name).withLabels(labels).withEnv(env).withHostName(name).withHealthcheck(healthCheck);
@@ -290,7 +306,7 @@ public class DockerService extends DockerServiceUtils {
         dockerClient.execStartCmd(id).exec(callBack).awaitCompletion();
     }
 
-    public void copyFiles(String containerId, String containerPath, 
Map<String, String> files, boolean dirChildrenOnly) throws IOException {
+    protected void copyFiles(String containerId, String containerPath, 
Map<String, String> files, boolean dirChildrenOnly) throws IOException {
         String temp = codeService.saveProjectFilesInTemp(files);
         
dockerClient.copyArchiveToContainerCmd(containerId).withRemotePath(containerPath)
                 
.withDirChildrenOnly(dirChildrenOnly).withHostResource(temp).exec();
@@ -355,7 +371,7 @@ public class DockerService extends DockerServiceUtils {
         List<Container> containers = findContainer(name);
         if (containers.size() == 1) {
             Container container = containers.get(0);
-            if (container.getState().equals("running")) {
+            if (container.getState().equals("running") || 
container.getState().equals("paused")) {
                 getDockerClient().stopContainerCmd(container.getId()).exec();
             }
         }
@@ -369,20 +385,31 @@ public class DockerService extends DockerServiceUtils {
         }
     }
 
-    public void pullImage(String image) throws InterruptedException {
+    public void pullImage(String image, boolean pullAlways) throws 
InterruptedException {
         List<Image> images = 
getDockerClient().listImagesCmd().withShowAll(true).exec();
         List<String> tags = images.stream()
                 .map(i -> 
Arrays.stream(i.getRepoTags()).collect(Collectors.toList()))
                 .flatMap(Collection::stream)
                 .toList();
 
-        if (!images.stream().anyMatch(i -> tags.contains(image))) {
-            ResultCallback.Adapter<PullResponseItem> pull = 
getDockerClient().pullImageCmd(image).start().awaitCompletion();
+        if (pullAlways || !images.stream().anyMatch(i -> 
tags.contains(image))) {
+            var callback = new PullCallback(LOGGER::info);
+            getDockerClient().pullImageCmd(image).exec(callback);
+            callback.awaitCompletion();
         }
     }
 
     private DockerClientConfig getDockerClientConfig() {
+        LOGGER.info("Docker Client Configuring....");
+        LOGGER.info("Docker Client Registry " + registry);
+        LOGGER.info("Docker Client Username " + (username.isPresent() ? "is 
not empty " : "is empty"));
+        LOGGER.info("Docker Client Password " + (password.isPresent() ? "is 
not empty " : "is empty"));
         DefaultDockerClientConfig.Builder builder =  
DefaultDockerClientConfig.createDefaultConfigBuilder();
+        if (!Objects.equals(registry, "registry:5000") && username.isPresent() 
&& password.isPresent()) {
+            builder.withRegistryUrl(registry);
+            builder.withRegistryUsername(username.get());
+            builder.withRegistryPassword(password.get());
+        }
         return builder.build();
     }
 
diff --git 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/PullCallback.java
 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/PullCallback.java
new file mode 100644
index 00000000..3f87e3b4
--- /dev/null
+++ 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/PullCallback.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.camel.karavan.docker;
+
+import com.github.dockerjava.api.async.ResultCallback;
+import com.github.dockerjava.api.model.PullResponseItem;
+
+import java.util.function.Consumer;
+
+public class PullCallback extends ResultCallback.Adapter<PullResponseItem> {
+
+    private final Consumer<String> action;
+
+    public PullCallback(Consumer<String> action) {
+        this.action = action;
+    }
+
+    @Override
+    public void onNext(PullResponseItem item) {
+        StringBuilder line = new StringBuilder();
+        if (item.getId() != null) {
+            line.append("Layer ").append(item.getId()).append(", ");
+        }
+        line.append(item.getStatus()).append(" ");
+        if (item.getProgressDetail() != null && 
item.getProgressDetail().getCurrent() != null && 
item.getProgressDetail().getTotal() != null) {
+            long progress = (long) 
((item.getProgressDetail().getCurrent().doubleValue() / 
item.getProgressDetail().getTotal().doubleValue()) * 100);
+            line.append(" ").append(progress).append("%");
+        }
+        action.accept(line.toString());
+    }
+
+}
diff --git 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/ProjectService.java
 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/ProjectService.java
index 37e71092..fca9c3c1 100644
--- 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/ProjectService.java
+++ 
b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/ProjectService.java
@@ -60,8 +60,6 @@ public class ProjectService implements HealthCheck {
     @ConfigProperty(name = "karavan.environment")
     String environment;
 
-
-
     @Inject
     InfinispanService infinispanService;
 
@@ -110,8 +108,7 @@ public class ProjectService implements HealthCheck {
             } else {
                 Map<String, String> files = 
codeService.getProjectFilesForDevMode(project.getProjectId(), true);
 
-                ProjectFile compose = 
infinispanService.getProjectFile(project.getProjectId(), 
PROJECT_COMPOSE_FILENAME);
-                DockerComposeService dcs = 
DockerComposeConverter.fromCode(compose.getCode(), project.getProjectId());
+                DockerComposeService dcs = 
codeService.getDockerComposeService(project.getProjectId());
                 dockerForKaravan.runProjectInDevMode(project.getProjectId(), 
jBangOptions, dcs.getPortsMap(), files);
             }
             return containerName;
@@ -150,7 +147,6 @@ public class ProjectService implements HealthCheck {
 
     public List<Project> getAllProjects(String type) {
         if (infinispanService.isReady()) {
-            List<ProjectFile> files = 
infinispanService.getProjectFilesByName(PROJECT_COMPOSE_FILENAME);
             return infinispanService.getProjects().stream()
                     .filter(p -> type == null || 
Objects.equals(p.getType().name(), type))
                     .sorted(Comparator.comparing(Project::getProjectId))
@@ -245,8 +241,7 @@ public class ProjectService implements HealthCheck {
     }
 
     public Integer getProjectPort(String projectId) {
-        ProjectFile composeFile = infinispanService.getProjectFile(projectId, 
PROJECT_COMPOSE_FILENAME);
-        return codeService.getProjectPort(composeFile);
+        return codeService.getProjectPort(projectId);
     }
 
     //    @Retry(maxRetries = 100, delay = 2000)
@@ -399,24 +394,13 @@ public class ProjectService implements HealthCheck {
     }
 
     public void setProjectImage(String projectId, String imageName, boolean 
commit, String message) throws Exception {
-        ProjectFile file = infinispanService.getProjectFile(projectId, 
PROJECT_COMPOSE_FILENAME);
-        if (file != null) {
-            DockerComposeService service = 
DockerComposeConverter.fromCode(file.getCode(), projectId);
-            service.setImage(imageName);
-            String code = DockerComposeConverter.toCode(service);
-            file.setCode(code);
-            infinispanService.saveProjectFile(file);
-            if (commit) {
-                commitAndPushProject(projectId, message);
-            }
+        codeService.updateDockerComposeImage(projectId, imageName);
+        if (commit) {
+            commitAndPushProject(projectId, message);
         }
     }
 
     public DockerComposeService getProjectDockerComposeService(String 
projectId) {
-        ProjectFile file = infinispanService.getProjectFile(projectId, 
PROJECT_COMPOSE_FILENAME);
-        if (file != null) {
-            return DockerComposeConverter.fromCode(file.getCode(), projectId);
-        }
-        return null;
+        return codeService.getDockerComposeService(projectId);
     }
 }
diff --git a/karavan-web/karavan-app/src/main/webui/src/api/KaravanApi.tsx 
b/karavan-web/karavan-app/src/main/webui/src/api/KaravanApi.tsx
index 4452b2ca..8f584d93 100644
--- a/karavan-web/karavan-app/src/main/webui/src/api/KaravanApi.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/api/KaravanApi.tsx
@@ -463,12 +463,13 @@ export class KaravanApi {
         });
     }
 
-    static async manageContainer(environment: string,
+    static async manageContainer(projectId: string,
                                  type: 'devmode' | 'devservice' | 'project' | 
'internal' | 'build' | 'unknown',
                                  name: string,
-                                 command: 'run' | 'pause' | 'stop' | 'delete',
-                                 after: (res: AxiosResponse<any>) => void) {
-        instance.post('/api/container/' + environment + '/' + type + "/" + 
name, {command: command})
+                                 command: 'deploy' | 'run' | 'pause' | 'stop' 
| 'delete',
+                                 pullImage: boolean,
+                                 after: (res: AxiosResponse<any> | any) => 
void) {
+        instance.post('/api/container/' + projectId + '/' + type + "/" + name, 
{command: command, pullImage: pullImage})
             .then(res => {
                 after(res);
             }).catch(err => {
@@ -476,8 +477,8 @@ export class KaravanApi {
         });
     }
 
-    static async deleteContainer(environment: string, type: 'devmode' | 
'devservice' | 'project' | 'internal' | 'build' | 'unknown', name: string, 
after: (res: AxiosResponse<any>) => void) {
-        instance.delete('/api/container/' + environment + '/' + type + "/" + 
name)
+    static async deleteContainer(projectId: string, type: 'devmode' | 
'devservice' | 'project' | 'internal' | 'build' | 'unknown', name: string, 
after: (res: AxiosResponse<any>) => void) {
+        instance.delete('/api/container/' + projectId + '/' + type + "/" + 
name)
             .then(res => {
                 after(res);
             }).catch(err => {
diff --git a/karavan-web/karavan-app/src/main/webui/src/api/ProjectService.ts 
b/karavan-web/karavan-app/src/main/webui/src/api/ProjectService.ts
index 26400e4d..3c1588bc 100644
--- a/karavan-web/karavan-app/src/main/webui/src/api/ProjectService.ts
+++ b/karavan-web/karavan-app/src/main/webui/src/api/ProjectService.ts
@@ -61,7 +61,7 @@ export class ProjectService {
 
     public static stopDevModeContainer(project: Project) {
         useDevModeStore.setState({status: 'wip'})
-        KaravanApi.manageContainer('dev', 'devmode', project.projectId, 
'stop', res => {
+        KaravanApi.manageContainer(project.projectId, 'devmode', 
project.projectId, 'stop',  false,res => {
             useDevModeStore.setState({status: 'none'})
             if (res.status === 200) {
                 useLogStore.setState({showLog: false, type: 'container'})
@@ -73,7 +73,7 @@ export class ProjectService {
 
     public static pauseDevModeContainer(project: Project) {
         useDevModeStore.setState({status: 'wip'})
-        KaravanApi.manageContainer('dev', 'devmode', project.projectId, 
'pause', res => {
+        KaravanApi.manageContainer(project.projectId, 'devmode', 
project.projectId, 'pause', false,res => {
             useDevModeStore.setState({status: 'none'})
             if (res.status === 200) {
                 useLogStore.setState({showLog: false, type: 'container'})
diff --git a/karavan-web/karavan-app/src/main/webui/src/api/ProjectStore.ts 
b/karavan-web/karavan-app/src/main/webui/src/api/ProjectStore.ts
index e1c5d47c..23d90b90 100644
--- a/karavan-web/karavan-app/src/main/webui/src/api/ProjectStore.ts
+++ b/karavan-web/karavan-app/src/main/webui/src/api/ProjectStore.ts
@@ -36,6 +36,9 @@ interface AppConfigState {
     setConfig: (config: AppConfig) => void;
     readiness: any;
     setReadiness: (readiness: any) => void;
+    selectedEnv: string[];
+    setSelectedEnv: (selectedEnv: string[]) => void;
+    selectEnvironment: (name: string, selected: boolean) => void;
 }
 
 export const useAppConfigStore = createWithEqualityFn<AppConfigState>((set) => 
({
@@ -57,6 +60,27 @@ export const useAppConfigStore = 
createWithEqualityFn<AppConfigState>((set) => (
             }
         });
     },
+    selectedEnv: [],
+    setSelectedEnv: (selectedEnv: string[])   => {
+        set((state: AppConfigState) => {
+            state.selectedEnv.length = 0;
+            state.selectedEnv.push(...selectedEnv);
+            return {selectedEnv: state.selectedEnv};
+        });
+    },
+    selectEnvironment(name: string, selected: boolean) {
+        console.log(name, selected)
+        set((state: AppConfigState) => {
+            if (selected && !state.selectedEnv.includes(name)) {
+                state.selectedEnv.push(name);
+            } else if (!selected && state.selectedEnv.includes(name)) {
+                const filtered = state.selectedEnv.filter(e => e !== name);
+                state.selectedEnv.length = 0;
+                state.selectedEnv.push(...filtered);
+            }
+            return {selectedEnv: state.selectedEnv};
+        });
+    }
 }), shallow)
 
 
diff --git 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/code/model/DockerCompose.java
 b/karavan-web/karavan-app/src/main/webui/src/containers/ContainerPage.css
similarity index 51%
copy from 
karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/code/model/DockerCompose.java
copy to karavan-web/karavan-app/src/main/webui/src/containers/ContainerPage.css
index 856df6c5..6f32d1ef 100644
--- 
a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/code/model/DockerCompose.java
+++ b/karavan-web/karavan-app/src/main/webui/src/containers/ContainerPage.css
@@ -15,32 +15,15 @@
  * limitations under the License.
  */
 
-package org.apache.camel.karavan.code.model;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class DockerCompose {
-    private Map<String, DockerComposeService> services;
-
-    public DockerCompose() {
-    }
-
-    public DockerCompose(Map<String, DockerComposeService> services) {
-        this.services = services;
-    }
-
-    public static DockerCompose create(DockerComposeService service) {
-        Map<String, DockerComposeService> map = new HashMap<>();
-        map.put(service.getContainer_name(), service);
-        return new DockerCompose(map);
-    }
-
-    public Map<String, DockerComposeService> getServices() {
-        return services;
-    }
-
-    public void setServices(Map<String, DockerComposeService> services) {
-        this.services = services;
-    }
+.container-page {
+    display: flex;
+    flex-direction: column;
+    height: 100%;
 }
+
+.container-page-section {
+    background-color: var(--pf-v5-global--BackgroundColor--light-300);
+    flex-grow: 1;
+    flex-shrink: 1;
+    overflow: auto;
+}
\ No newline at end of file
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/containers/ContainerTableRow.tsx 
b/karavan-web/karavan-app/src/main/webui/src/containers/ContainerTableRow.tsx
index b93c8543..0e43e5f8 100644
--- 
a/karavan-web/karavan-app/src/main/webui/src/containers/ContainerTableRow.tsx
+++ 
b/karavan-web/karavan-app/src/main/webui/src/containers/ContainerTableRow.tsx
@@ -29,6 +29,8 @@ import {ContainerStatus} from "../api/ProjectModels";
 import PauseIcon from "@patternfly/react-icons/dist/esm/icons/pause-icon";
 import DeleteIcon from "@patternfly/react-icons/dist/js/icons/times-icon";
 import {KaravanApi} from "../api/KaravanApi";
+import {useAppConfigStore} from "../api/ProjectStore";
+import {shallow} from "zustand/shallow";
 
 interface Props {
     index: number
@@ -37,6 +39,7 @@ interface Props {
 
 export function ContainerTableRow(props: Props) {
 
+    const [config] = useAppConfigStore((state) => [state.config], shallow);
     const [isExpanded, setIsExpanded] = useState<boolean>(false);
     const [showConfirmation, setShowConfirmation] = useState<boolean>(false);
     const [command, setCommand] = useState<'run' | 'pause' | 'stop' | 
'delete'>();
@@ -50,14 +53,15 @@ export function ContainerTableRow(props: Props) {
 
     function getConfirmation() {
         return (<Modal
-            className="modal-delete"
+            className="modal-confirm"
             title="Confirmation"
+            variant={"small"}
             isOpen={showConfirmation}
             onClose={() => setShowConfirmation(false)}
             actions={[
                 <Button key="confirm" variant="primary" onClick={e => {
                     if (command) {
-                        KaravanApi.manageContainer(container.env, 
container.type, container.containerName, command, res => {
+                        KaravanApi.manageContainer(container.projectId, 
container.type, container.containerName, command, false,res => {
                         });
                         setCommand(undefined);
                         setShowConfirmation(false);
@@ -90,6 +94,9 @@ export function ContainerTableRow(props: Props) {
                         : undefined}
                     modifier={"fitContent"}>
                 </Td>
+                <Td>
+                    {container.env}
+                </Td>
                 <Td style={{verticalAlign: "middle"}} modifier={"fitContent"}>
                     <Badge className="badge">{container.type}</Badge>
                 </Td>
@@ -107,7 +114,7 @@ export function ContainerTableRow(props: Props) {
                     {inTransit && <Spinner size="lg" aria-label="spinner"/>}
                 </Td>
                 <Td>
-                    {container.type !== 'internal' &&
+                    {container.type !== 'internal' && container.env === 
config.environment &&
                         <Flex direction={{default: "row"}} flexWrap={{default: 
"nowrap"}}
                               spaceItems={{default: 'spaceItemsNone'}}>
                             <FlexItem>
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/containers/ContainersPage.tsx 
b/karavan-web/karavan-app/src/main/webui/src/containers/ContainersPage.tsx
index 5f8bae73..41d6b467 100644
--- a/karavan-web/karavan-app/src/main/webui/src/containers/ContainersPage.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/containers/ContainersPage.tsx
@@ -28,7 +28,8 @@ import {
     ToolbarItem, EmptyStateHeader
 } from '@patternfly/react-core';
 import '../designer/karavan.css';
-import {ContainerStatus, ProjectType} from "../api/ProjectModels";
+import './ContainerPage.css';
+import {ContainerStatus} from "../api/ProjectModels";
 import {
        TableVariant,
        Tbody,
@@ -46,16 +47,13 @@ import {useAppConfigStore, useStatusesStore} from 
"../api/ProjectStore";
 import {shallow} from "zustand/shallow";
 import {ContainerTableRow} from "./ContainerTableRow";
 import {ProjectService} from "../api/ProjectService";
-import {KaravanApi} from "../api/KaravanApi";
-import {DockerCompose, ServicesYaml} from "../api/ServiceModels";
 
 export function ContainersPage () {
 
-    const [config] = useAppConfigStore((state) => [state.config], shallow)
+    const [config, selectedEnv, selectEnvironment] = useAppConfigStore((state) 
=> [state.config,state.selectedEnv, state.selectEnvironment], shallow)
     const [containers] = useStatusesStore((state) => [state.containers, 
state.setContainers], shallow);
     const [filter, setFilter] = useState<string>('');
     const [loading] = useState<boolean>(true);
-    const [selectedEnv, setSelectedEnv] = 
useState<string[]>([config.environment]);
 
     useEffect(() => {
         const interval = setInterval(() => {
@@ -64,19 +62,6 @@ export function ContainersPage () {
         return () => clearInterval(interval);
     }, []);
 
-    function selectEnvironment(name: string, selected: boolean) {
-        if (selected && !selectedEnv.includes(name)) {
-            setSelectedEnv((state: string[]) => {
-                state.push(name);
-                return state;
-            })
-        } else if (!selected && selectedEnv.includes(name)) {
-            setSelectedEnv((state: string[]) => {
-                return state.filter(e => e !== name)
-            })
-        }
-    }
-
     function tools() {
         return (<Toolbar id="toolbar-group-types">
             <ToolbarContent>
@@ -104,18 +89,6 @@ export function ContainersPage () {
         </TextContent>);
     }
 
-    function getSelectedEnvironments(): string [] {
-        return config.environments.filter(e => selectedEnv.includes(e));
-    }
-
-    function getContainerByEnvironments(name: string): [string, 
ContainerStatus | undefined] [] {
-        return selectedEnv.map(e => {
-            const env: string = e as string;
-            const container = containers.find(d => d.containerName === name && 
d.env === env);
-            return [env, container];
-        });
-    }
-
     function getEmptyState() {
         return (
             <Tbody>
@@ -135,17 +108,20 @@ export function ContainersPage () {
         )
     }
 
-    const conts = containers.filter(d => 
d.containerName.toLowerCase().includes(filter));
+    const conts = containers
+        .filter(c => selectedEnv.includes(c.env))
+        .filter(d => d.containerName.toLowerCase().includes(filter));
     return (
-        <PageSection className="kamelet-section" padding={{default: 
'noPadding'}}>
+        <PageSection className="container-page" padding={{default: 
'noPadding'}}>
             <PageSection className="tools-section" padding={{default: 
'noPadding'}}>
                 <MainToolbar title={title()} tools={tools()}/>
             </PageSection>
-            <PageSection isFilled className="kamelets-page">
+            <PageSection isFilled className="container-page-section">
                 <Table aria-label="Projects" variant={TableVariant.compact}>
                     <Thead>
                         <Tr>
                             <Th modifier="fitContent" textCenter={true} />
+                            <Th modifier="fitContent" textCenter={true} 
key='env'>Env</Th>
                             <Th modifier="fitContent" textCenter={true} 
key='type'>Type</Th>
                             <Th  key='name'>Name</Th>
                             <Th modifier="fitContent" textCenter={true} 
key='cpuInfo'>CPU</Th>
@@ -155,7 +131,7 @@ export function ContainersPage () {
                         </Tr>
                     </Thead>
                     {conts?.map((container: ContainerStatus, index: number) => 
(
-                        <ContainerTableRow key={container.containerName} 
index={index} container={container}/>
+                        <ContainerTableRow 
key={`${container.containerName}-${container.env}`} index={index} 
container={container}/>
                     ))}
                     {conts?.length === 0 && getEmptyState()}
                 </Table>
diff --git a/karavan-web/karavan-app/src/main/webui/src/project/ProjectPage.tsx 
b/karavan-web/karavan-app/src/main/webui/src/project/ProjectPage.tsx
index 8928d4f9..95e72b12 100644
--- a/karavan-web/karavan-app/src/main/webui/src/project/ProjectPage.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/project/ProjectPage.tsx
@@ -25,7 +25,7 @@ import '../designer/karavan.css';
 import {ProjectToolbar} from "./ProjectToolbar";
 import {ProjectLogPanel} from "./log/ProjectLogPanel";
 import {Project} from "../api/ProjectModels";
-import {useAppConfigStore, useFileStore, useProjectsStore, useProjectStore} 
from "../api/ProjectStore";
+import {useAppConfigStore, useFilesStore, useFileStore, useProjectsStore, 
useProjectStore} from "../api/ProjectStore";
 import {MainToolbar} from "../designer/MainToolbar";
 import {ProjectTitle} from "./ProjectTitle";
 import {ProjectPanel} from "./ProjectPanel";
@@ -40,6 +40,7 @@ export function ProjectPage() {
 
     const [config] = useAppConfigStore((state) => [state.config], shallow)
     const {file, operation} = useFileStore();
+    const [files] = useFilesStore((s) => [s.files], shallow);
     const [projects] = useProjectsStore((state) => [state.projects], shallow)
     const [project, setProject, tabIndex, setTabIndex, refreshTrace] =
         useProjectStore((s) => [s.project, s.setProject, s.tabIndex, 
s.setTabIndex, s.refreshTrace], shallow);
@@ -72,11 +73,16 @@ export function ProjectPage() {
         return ['kamelets', 'templates', 
'services'].includes(project.projectId);
     }
 
+    function isEphemeral(): boolean {
+        return files.filter(f => f.name.endsWith(".camel.yaml") || f.name === 
'application.properties').length === 0;
+    }
+
     function showTabs(): boolean {
         return !isBuildIn() && !showFilePanel;
     }
 
     const buildIn = isBuildIn();
+    const ephemeral = isEphemeral();
     const showFilePanel = file !== undefined && operation === 'select';
     return (
         <PageSection className="project-page" padding={{default: 'noPadding'}}>
@@ -88,10 +94,10 @@ export function ProjectPage() {
                     <FlexItem className="project-tabs">
                         {showTabs() && <Tabs activeKey={tabIndex} 
onSelect={(event, tabIndex) => setTabIndex(tabIndex)}>
                             <Tab eventKey="files" title="Files"/>
-                            <Tab eventKey="topology" title="Topology"/>
-                            <Tab eventKey="dashboard" title="Dashboard"/>
-                            <Tab eventKey="trace" title="Trace"/>
-                            <Tab eventKey="build" title="Build"/>
+                            {!ephemeral && <Tab eventKey="topology" 
title="Topology"/>}
+                            {!ephemeral && <Tab eventKey="dashboard" 
title="Dashboard"/>}
+                            {!ephemeral && <Tab eventKey="trace" 
title="Trace"/>}
+                            {!ephemeral && <Tab eventKey="build" 
title="Build"/>}
                             <Tab eventKey="container" title="Container"/>
                         </Tabs>}
                     </FlexItem>
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/project/builder/BuildPanel.tsx 
b/karavan-web/karavan-app/src/main/webui/src/project/builder/BuildPanel.tsx
index f1dedba6..0fa657f6 100644
--- a/karavan-web/karavan-app/src/main/webui/src/project/builder/BuildPanel.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/project/builder/BuildPanel.tsx
@@ -54,7 +54,7 @@ export function BuildPanel () {
     function deleteEntity() {
         const buildName = getBuildName();
         if (buildName) {
-            KaravanApi.manageContainer(config.environment, 'build', buildName, 
'delete', res => {
+            KaravanApi.manageContainer(project.projectId, 'build', buildName, 
'delete', false,res => {
                 EventBus.sendAlert("Container deleted", "Container " + 
buildName + " deleted", 'info')
                 setShowLog(false, 'container', undefined)
             });
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/project/container/ContainerButtons.tsx
 
b/karavan-web/karavan-app/src/main/webui/src/project/container/ContainerButtons.tsx
index 788e1fdd..dfacb55f 100644
--- 
a/karavan-web/karavan-app/src/main/webui/src/project/container/ContainerButtons.tsx
+++ 
b/karavan-web/karavan-app/src/main/webui/src/project/container/ContainerButtons.tsx
@@ -16,15 +16,16 @@
  */
 
 import React, {useState} from 'react';
-import {Button, Flex, FlexItem, Modal, Spinner, Tooltip, TooltipPosition} from 
'@patternfly/react-core';
+import {Button, Flex, FlexItem, Modal, Spinner, Switch, Tooltip, 
TooltipPosition} from '@patternfly/react-core';
 import '../../designer/karavan.css';
 import DeleteIcon from "@patternfly/react-icons/dist/esm/icons/trash-icon";
+import StopIcon from "@patternfly/react-icons/dist/esm/icons/stop-icon";
+import DeployIcon from "@patternfly/react-icons/dist/esm/icons/upload-icon";
 import {useAppConfigStore, useDevModeStore, useLogStore, useProjectStore, 
useStatusesStore} from "../../api/ProjectStore";
 import {shallow} from "zustand/shallow";
 import RunIcon from "@patternfly/react-icons/dist/esm/icons/play-icon";
 import {KaravanApi} from "../../api/KaravanApi";
-import StopIcon from "@patternfly/react-icons/dist/js/icons/stop-icon";
-
+import {EventBus} from "../../designer/utils/EventBus";
 
 interface Props {
     env: string,
@@ -38,33 +39,25 @@ export function ContainerButtons (props: Props) {
     const [containers] = useStatusesStore((state) => [state.containers], 
shallow);
     const [setShowLog] = useLogStore((s) => [s.setShowLog], shallow);
 
+    const [pullImage, setPullImage] = useState<boolean>(false);
     const [showConfirmation, setShowConfirmation] = useState<boolean>(false);
-    const [actionType, setActionType] = useState<'run' | 'stop' | 
'delete'>('run');
+    const [actionType, setActionType] = useState<'deploy' | 'run' | 'stop' | 
'delete'>('run');
 
     const containerStatus = containers.filter(c => c.containerName === 
project.projectId).at(0);
-    const commands = containerStatus?.commands || ['run'];
+    const commands = containerStatus?.commands || ['deploy'];
+    const exists = containerStatus != undefined;
     const isRunning = containerStatus?.state === 'running';
     const inTransit = containerStatus?.inTransit;
     const isLoading = status === 'wip';
 
     function act() {
-        switch (actionType) {
-            case "run":
-                KaravanApi.manageContainer(props.env, 'project', 
project.projectId, 'run', res => {
-                    setShowLog(false, 'container', undefined)
-                });
-                break;
-            case "stop":
-                KaravanApi.manageContainer(props.env, 'project', 
project.projectId, 'stop', res => {
-                    setShowLog(false, 'container', undefined)
-                });
-                break;
-            case "delete":
-                KaravanApi.manageContainer(props.env, 'project', 
project.projectId, 'delete', res => {
-                    setShowLog(false, 'container', undefined)
-                });
-                break;
-        }
+        KaravanApi.manageContainer(project.projectId, 'project', 
project.projectId, actionType, pullImage,res => {
+            const response = res?.response;
+            if (response?.status === 500) {
+                EventBus.sendAlert('Error', response.data !== undefined && 
response.data.length > 0 ? response.data : response.statusText, 'warning')
+            }
+            setShowLog(false, 'container', undefined)
+        });
     }
 
     function getConfirmationModal() {
@@ -86,6 +79,14 @@ export function ContainerButtons (props: Props) {
             ]}
             onEscapePress={e => setShowConfirmation(false)}>
             <div>{"Confirm " + actionType + " container?"}</div>
+            {actionType === 'deploy' && <div>
+                <Switch
+                    label="Pull image"
+                    isChecked={pullImage}
+                    onChange={(_, checked) => setPullImage(checked)}
+                    isReversed
+                />
+            </div>}
         </Modal>)
     }
 
@@ -93,6 +94,18 @@ export function ContainerButtons (props: Props) {
         <FlexItem>
             {(inTransit || isLoading) && <Spinner size="lg" 
aria-label="spinner"/>}
         </FlexItem>
+        {!isRunning && config.infrastructure !== 'kubernetes' && 
commands.includes('deploy') && <FlexItem>
+            <Tooltip content="Deploy container" 
position={TooltipPosition.bottom}>
+                <Button size="sm"
+                        isDisabled={(!(commands.length === 0) && 
!commands.includes('deploy')) || inTransit}
+                        variant={"primary"}
+                        icon={<DeployIcon/>}
+                        onClick={() => {
+                            setActionType('deploy');
+                            setShowConfirmation(true);
+                        }}>Deploy</Button>
+            </Tooltip>
+        </FlexItem>}
         {!isRunning && config.infrastructure !== 'kubernetes' && <FlexItem>
             <Tooltip content="Run container" position={TooltipPosition.bottom}>
                 <Button size="sm"
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/project/container/ContainerPanel.tsx
 
b/karavan-web/karavan-app/src/main/webui/src/project/container/ContainerPanel.tsx
index 2e619023..39221675 100644
--- 
a/karavan-web/karavan-app/src/main/webui/src/project/container/ContainerPanel.tsx
+++ 
b/karavan-web/karavan-app/src/main/webui/src/project/container/ContainerPanel.tsx
@@ -19,18 +19,10 @@ import React, {useState} from 'react';
 import {
     Badge,
     Button,
-    Card,
-    CardBody,
-    DescriptionList,
-    DescriptionListDescription,
-    DescriptionListGroup,
-    DescriptionListTerm,
     Flex,
     FlexItem,
     Label,
     LabelGroup, Modal,
-    Tooltip,
-    TooltipPosition
 } from '@patternfly/react-core';
 import '../../designer/karavan.css';
 import UpIcon from "@patternfly/react-icons/dist/esm/icons/running-icon";
@@ -95,7 +87,9 @@ export function ContainerPanel (props: Props) {
     }
 
     const env = props.env;
-    const conts = containers.filter(d => d.projectId === project?.projectId && 
d.type === 'project');
+    const conts = containers
+        .filter(c => c.env == env)
+        .filter(d => d.projectId === project?.projectId && d.type === 
'project');
     return (
         <Flex justifyContent={{default: "justifyContentSpaceBetween"}}
               alignItems={{default: "alignItemsFlexStart"}}>
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/project/container/ProjectContainerTab.tsx
 
b/karavan-web/karavan-app/src/main/webui/src/project/container/ProjectContainerTab.tsx
index a08b320e..a4f525da 100644
--- 
a/karavan-web/karavan-app/src/main/webui/src/project/container/ProjectContainerTab.tsx
+++ 
b/karavan-web/karavan-app/src/main/webui/src/project/container/ProjectContainerTab.tsx
@@ -34,7 +34,7 @@ export function ProjectContainerTab() {
         <PageSection className="project-tab-panel project-build-panel" 
padding={{default: "padding"}}>
             <div>
                 {config.environments.map(env =>
-                    <Card className="project-status">
+                    <Card key={env} className="project-status">
                         <CardBody>
                             <DescriptionList isHorizontal 
horizontalTermWidthModifier={{default: '20ch'}}>
                                 <DescriptionListGroup>
@@ -47,14 +47,14 @@ export function ProjectContainerTab() {
                                     <DescriptionListGroup>
                                         
<DescriptionListTerm>Deployment</DescriptionListTerm>
                                         <DescriptionListDescription>
-                                            <DeploymentPanel key={env} 
env={env}/>
+                                            <DeploymentPanel env={env}/>
                                         </DescriptionListDescription>
                                     </DescriptionListGroup>
                                 }
                                 <DescriptionListGroup>
                                     
<DescriptionListTerm>Containers</DescriptionListTerm>
                                     <DescriptionListDescription>
-                                        <ContainerPanel key={env} env={env}/>
+                                        <ContainerPanel env={env}/>
                                     </DescriptionListDescription>
                                 </DescriptionListGroup>
                             </DescriptionList>
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/projects/ProjectsPage.tsx 
b/karavan-web/karavan-app/src/main/webui/src/projects/ProjectsPage.tsx
index 60cc0f65..05a68026 100644
--- a/karavan-web/karavan-app/src/main/webui/src/projects/ProjectsPage.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/projects/ProjectsPage.tsx
@@ -124,8 +124,8 @@ export function ProjectsPage () {
                         <Th key='projectId'>Project ID</Th>
                         <Th key='name'>Name</Th>
                         <Th key='description'>Description</Th>
-                        <Th key='commit'>Commit</Th>
-                        <Th key='deployment'>Environment</Th>
+                        <Th key='commit' modifier={"fitContent"}>Commit</Th>
+                        <Th key='deployment' 
modifier={"fitContent"}>Environment</Th>
                         <Th key='action'></Th>
                     </Tr>
                 </Thead>
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/projects/ProjectsTableRow.tsx 
b/karavan-web/karavan-app/src/main/webui/src/projects/ProjectsTableRow.tsx
index 1746eb7f..e8e8972b 100644
--- a/karavan-web/karavan-app/src/main/webui/src/projects/ProjectsTableRow.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/projects/ProjectsTableRow.tsx
@@ -16,22 +16,13 @@
  */
 
 import React from 'react';
-import {
-    Button,
-    Badge,
-    Tooltip,
-    Flex, FlexItem, Label
-} from '@patternfly/react-core';
+import {Badge, Button, Flex, FlexItem, Label, Tooltip} from 
'@patternfly/react-core';
 import '../designer/karavan.css';
-import { Td, Tr} from "@patternfly/react-table";
+import {Td, Tr} from "@patternfly/react-table";
 import DeleteIcon from "@patternfly/react-icons/dist/js/icons/times-icon";
 import CopyIcon from "@patternfly/react-icons/dist/esm/icons/copy-icon";
 import {Project} from '../api/ProjectModels';
-import {
-    useAppConfigStore,
-    useLogStore,
-    useProjectStore, useStatusesStore,
-} from "../api/ProjectStore";
+import {useAppConfigStore, useLogStore, useProjectStore, useStatusesStore,} 
from "../api/ProjectStore";
 import {shallow} from "zustand/shallow";
 import {useNavigate} from "react-router-dom";
 
@@ -56,14 +47,14 @@ export function ProjectsTableRow (props: Props) {
             const env: string = e as string;
             const status = config.infrastructure === 'kubernetes'
                 ? deployments.find(d => d.projectId === name && d.env === env)
-                : containers.find(d => d.containerName === name && d.env === 
env);
-            return [env, status];
+                : containers.find(d => d.projectId === name && d.env === env);
+            return [env, status != null];
         });
     }
 
     const project = props.project;
     const isBuildIn = ['kamelets', 'templates'].includes(project.projectId);
-    const commit = project.lastCommit ? project.lastCommit?.substr(0, 7) : 
"...";
+    const commit = project.lastCommit ? project.lastCommit?.substr(0, 7) : 
undefined;
     return (
         <Tr key={project.projectId}>
             <Td>
@@ -79,22 +70,20 @@ export function ProjectsTableRow (props: Props) {
             <Td>{project.name}</Td>
             <Td>{project.description}</Td>
             <Td isActionCell>
-                <Tooltip content={project.lastCommit} position={"bottom"}>
+                {commit && <Tooltip content={project.lastCommit} 
position={"bottom"}>
                     <Badge className="badge">{commit}</Badge>
-                </Tooltip>
+                </Tooltip>}
             </Td>
-            <Td noPadding style={{width: "180px"}}>
+            <Td noPadding>
                 {!isBuildIn &&
-                    <Flex direction={{default: "row"}}>
+                    <div style={{display: "flex", gap:"2px"}}>
                         {getStatusByEnvironments(project.projectId).map(value 
=> {
                             const active = value[1];
                             const color = active ? "green" : "grey"
                             const style = active ? {fontWeight: "bold"} : {}
-                            return <FlexItem className="badge-flex-item" 
key={value[0]}>
-                                <Label style={style} color={color} 
>{value[0]}</Label>
-                            </FlexItem>
+                            return <Label style={style} color={color} 
>{value[0]}</Label>
                         })}
-                    </Flex>
+                    </div>
                 }
             </Td>
             <Td className="project-action-buttons">
diff --git 
a/karavan-web/karavan-app/src/main/webui/src/services/ServicesTableRow.tsx 
b/karavan-web/karavan-app/src/main/webui/src/services/ServicesTableRow.tsx
index cb04b01f..0d52d7e0 100644
--- a/karavan-web/karavan-app/src/main/webui/src/services/ServicesTableRow.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/services/ServicesTableRow.tsx
@@ -59,7 +59,7 @@ export function ServicesTableRow (props: Props) {
                         <Tooltip content={"Start container"} 
position={"bottom"}>
                             <Button variant={"plain"} icon={<PlayIcon/>} 
isDisabled={!commands.includes('run') || inTransit}
                                     onClick={e => {
-                                        
KaravanApi.manageContainer(config.environment, 'devservice', 
service.container_name, 'run', res => {});
+                                        
KaravanApi.manageContainer(service.container_name, 'devservice', 
service.container_name, 'run', false,res => {});
                                     }}></Button>
                         </Tooltip>
                     </FlexItem>
@@ -75,7 +75,7 @@ export function ServicesTableRow (props: Props) {
                         <Tooltip content={"Stop container"} 
position={"bottom"}>
                             <Button variant={"plain"} icon={<StopIcon/>} 
isDisabled={!commands.includes('stop') || inTransit}
                                     onClick={e => {
-                                        
KaravanApi.manageContainer(config.environment, 'devservice', 
service.container_name, 'stop', res => {});
+                                        
KaravanApi.manageContainer(service.container_name, 'devservice', 
service.container_name, 'stop', false,res => {});
                                     }}></Button>
                         </Tooltip>
                     </FlexItem>
@@ -83,7 +83,7 @@ export function ServicesTableRow (props: Props) {
                         <Tooltip content={"Delete container"} 
position={"bottom"}>
                             <Button variant={"plain"} icon={<DeleteIcon/>} 
isDisabled={!commands.includes('delete') || inTransit}
                                     onClick={e => {
-                                        
KaravanApi.deleteContainer(config.environment, 'devservice', 
service.container_name, res => {});
+                                        
KaravanApi.deleteContainer(service.container_name, 'devservice', 
service.container_name, res => {});
                                     }}></Button>
                         </Tooltip>
                     </FlexItem>

Reply via email to