Skip to content

Commit c29dbce

Browse files
committed
-export option
1 parent 4ef0b62 commit c29dbce

File tree

2 files changed

+42
-6
lines changed

2 files changed

+42
-6
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ sshcont:
1010
bind address, 127.0.0.1:2222, use :2222 for all (default "127.0.0.1:2222")
1111
-cmd string
1212
Execute cmd after login, example: ls
13+
-export string
14+
Before removing, export container contents to specified directory, example: /tmp/
1315
-image string
1416
Force image to be executed
1517
-vol string

main.go

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"io"
2424
"log"
2525
"os"
26+
"path/filepath"
2627
"strings"
2728
"time"
2829

@@ -49,8 +50,13 @@ func main() {
4950
vol := flag.String("vol", "", "Share volume into container, example: /home/:/home_shared")
5051
image := flag.String("image", "", "Force image to be executed")
5152
cmd := flag.String("cmd", "", "Execute cmd after login, example: ls")
53+
exportFolder := flag.String("export", "", "Before removing, export container contents to specified directory, example: /tmp/")
5254
flag.Parse()
5355

56+
if *exportFolder != "" {
57+
*exportFolder = filepath.Clean(*exportFolder)
58+
}
59+
5460
ssh.Handle(func(sess ssh.Session) {
5561
InfoPrint("Connection from: [%s]", sess.RemoteAddr())
5662
var defaultImage = sess.User()
@@ -93,7 +99,7 @@ func main() {
9399
CgroupnsMode: "host",
94100
SecurityOpt: []string{"apparmor=unconfined"},
95101
}
96-
status, cleanup, err := dockerRun(cfg, hostcfg, sess, *cmd)
102+
status, cleanup, err := dockerRun(cfg, hostcfg, sess, *cmd, *exportFolder)
97103
defer cleanup()
98104
if err != nil {
99105
fmt.Fprintln(sess, err)
@@ -106,7 +112,11 @@ func main() {
106112
log.Fatal(ssh.ListenAndServe(*bindAddress, nil))
107113
}
108114

109-
func imageExistsLocally(ctx context.Context, imageName string, cli *client.Client) bool {
115+
func imageExistsLocally(
116+
ctx context.Context,
117+
imageName string,
118+
cli *client.Client,
119+
) bool {
110120
images, err := cli.ImageList(ctx, image.ListOptions{})
111121
if err != nil {
112122
ErrorPrint("Error listing images: %v", err)
@@ -124,7 +134,13 @@ func imageExistsLocally(ctx context.Context, imageName string, cli *client.Clien
124134
return false
125135
}
126136

127-
func waitForContainerReady(ctx context.Context, sess ssh.Session, cli *client.Client, containerID string, timeout time.Duration) error {
137+
func waitForContainerReady(
138+
ctx context.Context,
139+
sess ssh.Session,
140+
cli *client.Client,
141+
containerID string,
142+
timeout time.Duration,
143+
) error {
128144
deadline := time.Now().Add(timeout)
129145

130146
for time.Now().Before(deadline) {
@@ -156,7 +172,13 @@ func waitForContainerReady(ctx context.Context, sess ssh.Session, cli *client.Cl
156172

157173
return fmt.Errorf("timeout waiting for container to be ready")
158174
}
159-
func dockerRun(cfg *container.Config, hostcfg *container.HostConfig, sess ssh.Session, cmd string) (status int, cleanup func(), err error) {
175+
func dockerRun(
176+
cfg *container.Config,
177+
hostcfg *container.HostConfig,
178+
sess ssh.Session,
179+
cmd string,
180+
exportFolder string,
181+
) (status int, cleanup func(), err error) {
160182
docker, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
161183
if err != nil {
162184
panic(err)
@@ -275,14 +297,26 @@ func dockerRun(cfg *container.Config, hostcfg *container.HostConfig, sess ssh.Se
275297

276298
select {
277299
case <-outputErr:
278-
279300
execInspect, ierr := docker.ContainerExecInspect(ctx, execResp.ID)
280301
if ierr != nil {
281302
WarnPrint("Unable to inspect command exit code: %s", err.Error())
282303
}
283304
status = execInspect.ExitCode
284305
InfoPrint("Exit code from specified command: %d", status)
285-
306+
if exportFolder != "" {
307+
InfoPrint("Exporting container to : [%s/%s.tar]", exportFolder, resp.ID)
308+
stream, eErr := docker.ContainerExport(ctx, resp.ID)
309+
if eErr != nil {
310+
WarnPrint("Unable to create export context for container %s: %s", resp.ID, eErr.Error())
311+
}
312+
targetFile, fErr := os.Create(exportFolder + "/" + resp.ID + ".tar")
313+
if fErr != nil {
314+
WarnPrint("Unable to create export file for container %s: %s", resp.ID, fErr.Error())
315+
}
316+
io.Copy(targetFile, stream)
317+
targetFile.Close()
318+
stream.Close()
319+
}
286320
cleanup = func() {
287321
InfoPrint("Killing container: %s", resp.ID)
288322
docker.ContainerKill(ctx, resp.ID, "9")

0 commit comments

Comments
 (0)