@@ -3,6 +3,8 @@ package dockerfile
3
3
import (
4
4
"errors"
5
5
"fmt"
6
+ "os"
7
+ "path"
6
8
"path/filepath"
7
9
"strings"
8
10
@@ -99,23 +101,46 @@ func (g *FastGenerator) generate() (string, error) {
99
101
return "" , err
100
102
}
101
103
102
- tmpDir , err := BuildCogTempDir (g .Dir )
104
+ // Temp directories are used as bind mounts in docker build
105
+ // Separate them so that changes in one layer doesn't invalidate everything else
106
+
107
+ // Weights layer
108
+ // Includes file metadata, triggered by weights file changes
109
+ tmpWeightsDir , err := BuildCogTempDir (g .Dir , "weights" )
103
110
if err != nil {
104
111
return "" , err
105
112
}
106
-
107
- weights , err := weights .FindFastWeights (g .Dir , tmpDir )
113
+ weights , err := weights .FindFastWeights (g .Dir , tmpWeightsDir )
108
114
if err != nil {
109
115
return "" , err
110
116
}
111
117
112
- aptTarFile , err := g .generateAptTarball (tmpDir )
118
+ // APT layer
119
+ // Includes a tarball extracted from APT packages, triggered by system_packages changes
120
+ tmpAptDir , err := BuildCogTempDir (g .Dir , "apt" )
121
+ if err != nil {
122
+ return "" , err
123
+ }
124
+ aptTarFile , err := g .generateAptTarball (tmpAptDir )
113
125
if err != nil {
114
126
return "" , fmt .Errorf ("generate apt tarball: %w" , err )
115
127
}
116
128
129
+ // Monobase layer
130
+ // Includes an ENV file, triggered by Python, Torch, or CUDA version changes
131
+ tmpMonobaseDir , err := BuildCogTempDir (g .Dir , "monobase" )
132
+ if err != nil {
133
+ return "" , err
134
+ }
117
135
lines := []string {}
118
- lines , err = g .generateMonobase (lines , tmpDir )
136
+ lines , err = g .generateMonobase (lines , tmpMonobaseDir )
137
+ if err != nil {
138
+ return "" , err
139
+ }
140
+
141
+ // User layer
142
+ // Includes requirements.txt, triggered by python_requirements changes
143
+ tmpUserDir , err := BuildCogTempDir (g .Dir , "user" )
119
144
if err != nil {
120
145
return "" , err
121
146
}
@@ -125,7 +150,17 @@ func (g *FastGenerator) generate() (string, error) {
125
150
return "" , err
126
151
}
127
152
128
- lines , err = g .install (lines , weights , tmpDir , aptTarFile )
153
+ lines , err = g .installApt (lines , tmpAptDir , aptTarFile )
154
+ if err != nil {
155
+ return "" , err
156
+ }
157
+
158
+ lines , err = g .installPython (lines , tmpUserDir )
159
+ if err != nil {
160
+ return "" , err
161
+ }
162
+
163
+ lines , err = g .installSrc (lines , weights )
129
164
if err != nil {
130
165
return "" , err
131
166
}
@@ -139,12 +174,8 @@ func (g *FastGenerator) generate() (string, error) {
139
174
}
140
175
141
176
func (g * FastGenerator ) generateMonobase (lines []string , tmpDir string ) ([]string , error ) {
142
- lines = append (lines , []string {
143
- "# syntax=docker/dockerfile:1-labs" ,
144
- "FROM r8.im/monobase:latest" ,
145
- }... )
146
-
147
- lines = append (lines , []string {
177
+ var envs []string
178
+ envs = append (envs , []string {
148
179
// This installs latest version of coglet
149
180
"ENV R8_COG_VERSION=coglet" ,
150
181
}... )
@@ -162,7 +193,7 @@ func (g *FastGenerator) generateMonobase(lines []string, tmpDir string) ([]strin
162
193
return nil , fmt .Errorf ("CUDNN version must be <major> only, supported versions: %s" , strings .Join (g .matrix .CudnnVersions , ", " ))
163
194
}
164
195
165
- lines = append (lines , []string {
196
+ envs = append (envs , []string {
166
197
"ENV R8_CUDA_VERSION=" + cudaVersion ,
167
198
"ENV R8_CUDNN_VERSION=" + cudnnVersion ,
168
199
"ENV R8_CUDA_PREFIX=https://monobase-packages.replicate.delivery/cuda" ,
@@ -174,7 +205,7 @@ func (g *FastGenerator) generateMonobase(lines []string, tmpDir string) ([]strin
174
205
return nil , fmt .Errorf (
175
206
"Python version must be <major>.<minor>, supported versions: %s" , strings .Join (g .matrix .PythonVersions , ", " ))
176
207
}
177
- lines = append (lines , []string {
208
+ envs = append (envs , []string {
178
209
"ENV R8_PYTHON_VERSION=" + g .Config .Build .PythonVersion ,
179
210
}... )
180
211
@@ -183,7 +214,7 @@ func (g *FastGenerator) generateMonobase(lines []string, tmpDir string) ([]strin
183
214
if ! CheckMajorMinorPatch (torchVersion ) {
184
215
return nil , fmt .Errorf ("Torch version must be <major>.<minor>.<patch>: %s" , strings .Join (g .matrix .TorchVersions , ", " ))
185
216
}
186
- lines = append (lines , []string {
217
+ envs = append (envs , []string {
187
218
"ENV R8_TORCH_VERSION=" + torchVersion ,
188
219
}... )
189
220
}
@@ -194,19 +225,32 @@ func (g *FastGenerator) generateMonobase(lines []string, tmpDir string) ([]strin
194
225
g .Config .Build .PythonVersion , torchVersion , g .Config .Build .CUDA )
195
226
}
196
227
228
+ // The only input to monobase.build are these ENV vars
229
+ // Write them in tmp mount for layer caching
230
+ err := os .WriteFile (path .Join (tmpDir , "env.txt" ), []byte (strings .Join (envs , "\n " )), 0o644 )
231
+ if err != nil {
232
+ return nil , err
233
+ }
234
+
197
235
buildTmpMount , err := g .buildTmpMount (tmpDir )
198
236
if err != nil {
199
237
return nil , err
200
238
}
201
239
202
- return append (lines , []string {
240
+ lines = append (lines , []string {
241
+ "# syntax=docker/dockerfile:1-labs" ,
242
+ "FROM r8.im/monobase:latest" ,
243
+ }... )
244
+ lines = append (lines , envs ... )
245
+ lines = append (lines , []string {
203
246
"RUN " + strings .Join ([]string {
204
247
buildTmpMount ,
205
248
g .monobaseUsercacheMount (),
206
249
APT_CACHE_MOUNT ,
207
250
UV_CACHE_MOUNT ,
208
251
}, " " ) + " UV_CACHE_DIR=\" " + UV_CACHE_DIR + "\" UV_LINK_MODE=copy /opt/r8/monobase/run.sh monobase.build --mini --cache=" + MONOBASE_CACHE_PATH ,
209
- }... ), nil
252
+ }... )
253
+ return lines , nil
210
254
}
211
255
212
256
func (g * FastGenerator ) copyWeights (lines []string , weights []weights.Weight ) ([]string , error ) {
@@ -221,7 +265,7 @@ func (g *FastGenerator) copyWeights(lines []string, weights []weights.Weight) ([
221
265
return lines , nil
222
266
}
223
267
224
- func (g * FastGenerator ) install (lines []string , weights []weights. Weight , tmpDir string , aptTarFile string ) ([]string , error ) {
268
+ func (g * FastGenerator ) installApt (lines []string , tmpDir string , aptTarFile string ) ([]string , error ) {
225
269
// Install apt packages
226
270
buildTmpMount , err := g .buildTmpMount (tmpDir )
227
271
if err != nil {
@@ -230,9 +274,16 @@ func (g *FastGenerator) install(lines []string, weights []weights.Weight, tmpDir
230
274
if aptTarFile != "" {
231
275
lines = append (lines , "RUN " + buildTmpMount + " tar -xf \" " + filepath .Join ("/buildtmp" , aptTarFile )+ "\" -C /" )
232
276
}
277
+ return lines , nil
278
+ }
233
279
280
+ func (g * FastGenerator ) installPython (lines []string , tmpDir string ) ([]string , error ) {
234
281
// Install python packages
235
- requirementsFile , err := g .pythonRequirements (tmpDir )
282
+ buildTmpMount , err := g .buildTmpMount (tmpDir )
283
+ if err != nil {
284
+ return nil , err
285
+ }
286
+ requirementsFile , err := requirements .GenerateRequirements (tmpDir , g .Config )
236
287
if err != nil {
237
288
return nil , err
238
289
}
@@ -242,6 +293,11 @@ func (g *FastGenerator) install(lines []string, weights []weights.Weight, tmpDir
242
293
UV_CACHE_MOUNT ,
243
294
}, " " )+ " UV_CACHE_DIR=\" " + UV_CACHE_DIR + "\" UV_LINK_MODE=copy UV_COMPILE_BYTECODE=0 /opt/r8/monobase/run.sh monobase.user --requirements=/buildtmp/requirements.txt" )
244
295
}
296
+ return lines , nil
297
+ }
298
+
299
+ func (g * FastGenerator ) installSrc (lines []string , weights []weights.Weight ) ([]string , error ) {
300
+ // Install /src
245
301
246
302
// Copy over source / without weights
247
303
copyCommand := "COPY --link --exclude='.cog' "
@@ -263,10 +319,6 @@ func (g *FastGenerator) install(lines []string, weights []weights.Weight, tmpDir
263
319
return lines , nil
264
320
}
265
321
266
- func (g * FastGenerator ) pythonRequirements (tmpDir string ) (string , error ) {
267
- return requirements .GenerateRequirements (tmpDir , g .Config )
268
- }
269
-
270
322
func (g * FastGenerator ) entrypoint (lines []string ) ([]string , error ) {
271
323
return append (lines , []string {
272
324
"WORKDIR /src" ,
0 commit comments