Compile returns the build parameters for the workspace. devcontainerDir is the path to the directory where the devcontainer.json file is located. scratchDir is the path to the directory where the Dockerfile will be written to if one doesn't exist.
(fs billy.Filesystem, devcontainerDir, scratchDir string, fallbackDockerfile, workspaceFolder string, useBuildContexts bool, lookupEnv func(string) (string, bool))
| 138 | // is located. scratchDir is the path to the directory where the Dockerfile will |
| 139 | // be written to if one doesn't exist. |
| 140 | func (s *Spec) Compile(fs billy.Filesystem, devcontainerDir, scratchDir string, fallbackDockerfile, workspaceFolder string, useBuildContexts bool, lookupEnv func(string) (string, bool)) (*Compiled, error) { |
| 141 | params := &Compiled{ |
| 142 | User: s.ContainerUser, |
| 143 | ContainerEnv: s.ContainerEnv, |
| 144 | RemoteEnv: s.RemoteEnv, |
| 145 | } |
| 146 | |
| 147 | if s.Image != "" { |
| 148 | // We just write the image to a file and return it. |
| 149 | dockerfilePath := filepath.Join(scratchDir, "Dockerfile") |
| 150 | file, err := fs.OpenFile(dockerfilePath, os.O_CREATE|os.O_WRONLY, 0o644) |
| 151 | if err != nil { |
| 152 | return nil, fmt.Errorf("open dockerfile: %w", err) |
| 153 | } |
| 154 | defer file.Close() |
| 155 | _, err = file.Write([]byte("FROM " + s.Image)) |
| 156 | if err != nil { |
| 157 | return nil, err |
| 158 | } |
| 159 | params.DockerfilePath = dockerfilePath |
| 160 | params.BuildContext = scratchDir |
| 161 | } else { |
| 162 | // Deprecated values! |
| 163 | if s.Dockerfile != "" { |
| 164 | s.Build.Dockerfile = s.Dockerfile |
| 165 | } |
| 166 | if s.Context != "" { |
| 167 | s.Build.Context = s.Context |
| 168 | } |
| 169 | |
| 170 | if s.Build.Dockerfile != "" { |
| 171 | params.DockerfilePath = filepath.Join(devcontainerDir, s.Build.Dockerfile) |
| 172 | } else { |
| 173 | params.DockerfilePath = fallbackDockerfile |
| 174 | } |
| 175 | params.BuildContext = filepath.Join(devcontainerDir, s.Build.Context) |
| 176 | } |
| 177 | |
| 178 | // It's critical that the Dockerfile produced is deterministic. |
| 179 | buildArgkeys := make([]string, 0, len(s.Build.Args)) |
| 180 | for key := range s.Build.Args { |
| 181 | buildArgkeys = append(buildArgkeys, key) |
| 182 | } |
| 183 | sort.Strings(buildArgkeys) |
| 184 | |
| 185 | buildArgs := make([]string, 0) |
| 186 | for _, key := range buildArgkeys { |
| 187 | val := SubstituteVars(s.Build.Args[key], workspaceFolder, lookupEnv) |
| 188 | buildArgs = append(buildArgs, key+"="+val) |
| 189 | } |
| 190 | params.BuildArgs = buildArgs |
| 191 | |
| 192 | dockerfile, err := fs.Open(params.DockerfilePath) |
| 193 | if err != nil { |
| 194 | return nil, fmt.Errorf("open dockerfile %q: %w", params.DockerfilePath, err) |
| 195 | } |
| 196 | defer dockerfile.Close() |
| 197 | dockerfileContent, err := io.ReadAll(dockerfile) |