github.com/cloudcredo/cloudrocker@v0.0.0-20160108110610-1320f8cc2dfd/docker/parser.go (about) 1 package docker 2 3 import ( 4 "io/ioutil" 5 "log" 6 "os/user" 7 "sort" 8 "strconv" 9 "strings" 10 11 "github.com/cloudcredo/cloudrocker/Godeps/_workspace/src/github.com/fsouza/go-dockerclient" 12 "github.com/cloudcredo/cloudrocker/config" 13 ) 14 15 func ParseCreateContainerOptions(config *config.ContainerConfig) docker.CreateContainerOptions { 16 var options = docker.CreateContainerOptions{ 17 Name: config.ContainerName, 18 Config: &docker.Config{ 19 User: userID(), 20 Env: parseEnvVars(config.EnvVars), 21 Image: config.SrcImageTag, 22 Cmd: config.Command, 23 Mounts: parseMounts(config.Mounts), 24 AttachStdout: parseDaemon(config.Daemon), 25 AttachStderr: parseDaemon(config.Daemon), 26 ExposedPorts: parseExposedPorts(config.PublishedPorts), 27 }, 28 HostConfig: &docker.HostConfig{ 29 Binds: parseBinds(config.Mounts), 30 PortBindings: parsePublishedPorts(config.PublishedPorts), 31 NetworkMode: "bridge", 32 }, 33 } 34 return options 35 } 36 37 func WriteRuntimeDockerfile(config *config.ContainerConfig) { 38 var dockerfile string 39 40 dockerfile = runtimeInitialDockerfileString() 41 dockerfile = dockerfile + envVarDockerfileString(config.EnvVars) 42 dockerfile = dockerfile + commandDockerfileString(config.Command) 43 44 ioutil.WriteFile(config.DropletDir+"/Dockerfile", []byte(dockerfile), 0644) 45 } 46 47 func WriteBaseImageDockerfile(config *config.ContainerConfig) { 48 var dockerfile string 49 50 dockerfile = baseImageDockerfileString(config.SrcImageTag) 51 52 ioutil.WriteFile(config.BaseConfigDir+"/Dockerfile", []byte(dockerfile), 0644) 53 } 54 55 func userID() string { 56 var thisUser *user.User 57 var err error 58 if thisUser, err = user.Current(); err != nil { 59 log.Fatalf(" %s", err) 60 } 61 return thisUser.Uid 62 } 63 64 type ByHostPath []docker.Mount 65 66 func (slice ByHostPath) Len() int { return len(slice) } 67 func (slice ByHostPath) Swap(i, j int) { slice[i], slice[j] = slice[j], slice[i] } 68 func (slice ByHostPath) Less(i, j int) bool { return slice[i].Source < slice[j].Source } 69 70 func parseMounts(mounts map[string]string) (parsedMounts []docker.Mount) { 71 for hostPath, containerPath := range mounts { 72 parsedMounts = append(parsedMounts, docker.Mount{ 73 Source: hostPath, 74 Destination: containerPath, 75 RW: true, 76 }) 77 } 78 sort.Sort(ByHostPath(parsedMounts)) 79 return 80 } 81 82 func parseBinds(mounts map[string]string) (parsedBinds []string) { 83 for hostPath, containerPath := range mounts { 84 parsedBinds = append(parsedBinds, hostPath+":"+containerPath) 85 } 86 sort.Strings(parsedBinds) 87 return 88 } 89 90 func parseExposedPorts(publishedPorts map[int]int) map[docker.Port]struct{} { 91 var parsedExposedPorts = make(map[docker.Port]struct{}) 92 for hostPort := range publishedPorts { 93 parsedExposedPorts[convertHostPort(hostPort)] = struct{}{} 94 } 95 return parsedExposedPorts 96 } 97 98 func parsePublishedPorts(publishedPorts map[int]int) map[docker.Port][]docker.PortBinding { 99 var parsedPublishedPorts = make(map[docker.Port][]docker.PortBinding) 100 for hostPort, containerPort := range publishedPorts { 101 parsedPublishedPorts[convertHostPort(hostPort)] = []docker.PortBinding{ 102 { 103 HostPort: strconv.Itoa(containerPort), 104 }, 105 } 106 } 107 return parsedPublishedPorts 108 } 109 110 func convertHostPort(hostPort int) docker.Port { 111 return docker.Port(strconv.Itoa(hostPort) + "/tcp") 112 } 113 114 func parseEnvVars(envVars map[string]string) (parsedEnvVars []string) { 115 for key, val := range envVars { 116 if val != "" { 117 parsedEnvVars = append(parsedEnvVars, key+"="+val) 118 } 119 } 120 sort.Strings(parsedEnvVars) 121 return 122 } 123 124 func parseDaemon(daemon bool) bool { 125 return !daemon 126 } 127 128 func runtimeInitialDockerfileString() string { 129 return `FROM cloudrocker-base:latest 130 COPY droplet.tgz /app/ 131 RUN chown vcap:vcap /app && cd /app && su vcap -c "tar zxf droplet.tgz" && rm droplet.tgz 132 EXPOSE 8080 133 USER vcap 134 WORKDIR /app 135 ` 136 } 137 138 func baseImageDockerfileString(srcImageTag string) string { 139 return `FROM ` + srcImageTag + ` 140 RUN id vcap || /usr/sbin/useradd -mU -u ` + userID() + ` -d /app -s /bin/bash vcap 141 RUN mkdir -p /app/tmp && chown -R vcap:vcap /app 142 ` 143 } 144 145 func envVarDockerfileString(envVars map[string]string) string { 146 var envVarStrings []string 147 for envVarKey, envVarVal := range envVars { 148 if envVarVal != "" { 149 envVarStrings = append(envVarStrings, "ENV "+envVarKey+" "+envVarVal+"\n") 150 } 151 } 152 sort.Strings(envVarStrings) 153 return strings.Join(envVarStrings, "") 154 } 155 156 func commandDockerfileString(command []string) string { 157 for index, commandElement := range command { 158 command[index] = strings.Replace(commandElement, `"`, `\"`, -1) 159 } 160 commandString := `CMD ["` 161 commandString = commandString + strings.Join(command, `", "`) 162 commandString = commandString + "\"]\n" 163 return commandString 164 }