Skip to content
This repository has been archived by the owner on Oct 29, 2024. It is now read-only.

Commit

Permalink
Run container from volume
Browse files Browse the repository at this point in the history
  • Loading branch information
felipecruz91 committed Jun 26, 2022
1 parent 1c974e9 commit 07b34f5
Show file tree
Hide file tree
Showing 2 changed files with 228 additions and 1 deletion.
32 changes: 31 additions & 1 deletion ui/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@ import {
ExitToApp as ExitToAppIcon,
CopyAll as CopyAllIcon,
Devices as DevicesIcon,
PlayArrow as PlayArrowIcon,
} from "@mui/icons-material";
import ExportDialog from "./components/ExportDialog";
import ImportDialog from "./components/ImportDialog";
import SaveDialog from "./components/SaveDialog";
import LoadDialog from "./components/LoadDialog";
import CloneDialog from "./components/CloneDialog";
import TransferDialog from "./components/TransferDialog";
import RunContainerDialog from "./components/RunContainerDialog";
import { MyContext } from ".";

const client = createDockerDesktopClient();
Expand Down Expand Up @@ -61,7 +63,8 @@ export function App() {
const [openCloneDialog, setOpenCloneDialog] = React.useState<boolean>(false);
const [openTransferDialog, setOpenTransferDialog] =
React.useState<boolean>(false);

const [openRunContainerDialog, setOpenRunContainerDialog] =
React.useState<boolean>(false);
const ddClient = useDockerDesktopClient();

const columns = [
Expand Down Expand Up @@ -110,6 +113,17 @@ export function App() {
onClick={handleNavigate(params.row)}
disabled={actionInProgress}
/>,
<GridActionsCellItem
key={"action_run_container_from_volume_" + params.row.id}
icon={
<Tooltip title="Run container from volume">
<PlayArrowIcon>Run container from volume</PlayArrowIcon>
</Tooltip>
}
label="Run container from volume"
onClick={handleRunContainer(params.row)}
disabled={actionInProgress}
/>,
<GridActionsCellItem
key={"action_clone_volume_" + params.row.id}
icon={
Expand Down Expand Up @@ -189,6 +203,11 @@ export function App() {
ddClient.desktopUI.navigate.viewVolume(row.volumeName);
};

const handleRunContainer = (row) => () => {
setOpenRunContainerDialog(true);
context.actions.setVolumeName(row.volumeName);
};

const handleClone = (row) => () => {
setOpenCloneDialog(true);
context.actions.setVolumeName(row.volumeName);
Expand Down Expand Up @@ -351,6 +370,10 @@ export function App() {
}
};

const handleRunContainerDialogClose = () => {
setOpenRunContainerDialog(false);
};

const handleExportDialogClose = () => {
setOpenExportDialog(false);
};
Expand Down Expand Up @@ -424,6 +447,13 @@ export function App() {
/>
</Grid>

{openRunContainerDialog && (
<RunContainerDialog
open={openRunContainerDialog}
onClose={handleRunContainerDialogClose}
/>
)}

{openExportDialog && (
<ExportDialog
open={openExportDialog}
Expand Down
197 changes: 197 additions & 0 deletions ui/src/components/RunContainerDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
import React, { useContext } from "react";
import {
Button,
TextField,
Grid,
Backdrop,
CircularProgress,
} from "@mui/material";
import Dialog from "@mui/material/Dialog";
import DialogActions from "@mui/material/DialogActions";
import DialogContent from "@mui/material/DialogContent";
import DialogContentText from "@mui/material/DialogContentText";
import DialogTitle from "@mui/material/DialogTitle";
import { createDockerDesktopClient } from "@docker/extension-api-client";

import { MyContext } from "../index";

const client = createDockerDesktopClient();

function useDockerDesktopClient() {
return client;
}

export default function RunContainerDialog({ ...props }) {
console.log("RunContainerDialog component rendered.");
const ddClient = useDockerDesktopClient();
const context = useContext(MyContext);

const [image, setImage] = React.useState<string>("");
const [containerPath, setContainerPath] = React.useState<string>("");
const [containerName, setContainerName] = React.useState<string>(
`container-from-vol-${context.store.volumeName}`
);
const [containerEnvVars, setContainerEnvVars] = React.useState<string>("");
const [containerPorts, setContainerPorts] = React.useState<string>("");
const [actionInProgress, setActionInProgress] =
React.useState<boolean>(false);

const runContainer = async () => {
setActionInProgress(true);
try {
console.log(
`Running a container from volume ${context.store.volumeName}...`
);

let args = [
`--name=${containerName}`,
"-d",
"-i",
`-v=${context.store.volumeName}:${containerPath}`,
];

if (containerPorts !== "") {
const ports = containerPorts.split(",");
for (let i = 0; i < ports.length; i++) {
args.push(`-p=${ports[i]}`);
}
}

if (containerEnvVars !== "") {
const envVars = containerEnvVars.split(",");
for (let i = 0; i < envVars.length; i++) {
args.push(`-e=${envVars[i]}`);
}
}

args.push(image);

console.log(args.join(" "));

const runOutput = await ddClient.docker.cli.exec("run", args);
console.log(runOutput);
if (runOutput.stderr !== "") {
ddClient.desktopUI.toast.error(runOutput.stderr);
return;
}

ddClient.desktopUI.toast.success(
`Container ${containerName} is running from volume ${context.store.volumeName}`
);
} catch (error) {
ddClient.desktopUI.toast.error(
`Failed to run container volume ${context.store.volumeName}: ${error.stderr} Exit code: ${error.code}`
);
} finally {
setActionInProgress(false);
props.onClose();
}
};

return (
<Dialog open={props.open} onClose={props.onClose}>
<DialogTitle>Run a container from a volume</DialogTitle>
<DialogContent>
<Backdrop
sx={{
backgroundColor: "rgba(245,244,244,0.4)",
zIndex: (theme) => theme.zIndex.drawer + 1,
}}
open={actionInProgress}
>
<CircularProgress color="info" />
</Backdrop>
<DialogContentText>
Use a volume from a backup and attach it to a new container.
</DialogContentText>

<Grid container direction="column" spacing={2}>
<Grid item>
<TextField
required
autoFocus
margin="dense"
id="image-name"
label="Image"
fullWidth
variant="standard"
placeholder="redis:latest"
spellCheck={false}
onChange={(e) => {
setImage(e.target.value);
}}
/>
</Grid>
<Grid item>
<TextField
required
margin="dense"
id="container-name"
label="Container name"
fullWidth
variant="standard"
defaultValue={containerName}
spellCheck={false}
onChange={(e) => {
setContainerName(e.target.value);
}}
/>
</Grid>
<Grid item>
<TextField
required
margin="dense"
id="container-path"
label="Container path"
fullWidth
variant="standard"
placeholder="/data"
spellCheck={false}
onChange={(e) => {
setContainerPath(e.target.value);
}}
/>
</Grid>

<Grid item>
<TextField
margin="dense"
id="container-ports"
label="Port(s)"
fullWidth
variant="standard"
placeholder="8080:80,8081:81"
spellCheck={false}
onChange={(e) => {
setContainerPorts(e.target.value);
}}
/>
</Grid>
<Grid item>
<TextField
margin="dense"
id="container-env-vars"
label="Environment variables"
fullWidth
variant="standard"
placeholder="KEY=VALUE,FOO=BAR"
spellCheck={false}
onChange={(e) => {
setContainerEnvVars(e.target.value);
}}
/>
</Grid>
</Grid>
</DialogContent>
<DialogActions>
<Button onClick={props.onClose}>Cancel</Button>
<Button
onClick={runContainer}
disabled={containerPath === "" || containerPath === ""}
>
Run
</Button>
</DialogActions>
</Dialog>
);
}

0 comments on commit 07b34f5

Please sign in to comment.