如何定义抖动规则来构建 docker 图像?
How to define a shake rule to build docker images?
我有一个 shake 构建(版本 0.16.4),它从 Dockerfile
和其他支持文件中构建了很多 docker 图像。我想将所有这些构建在单个 "rule" 中,其输出将是 docker 图像。我已经阅读 How to define a timer rule in Shake 关于 shake 中的自定义规则,但这并没有解释如何定义自己的 output。
我想表达一下
Image "foo" "latest" %> \ img -> do
need [ ... ]
buildDockerImage "docker/foo" img
Image "bar" "latest" %> \ img ->
needImage "foo" "latest"
...
然后让抖动跟踪图像作为依赖项。我已经在旧版本的 shake 中实现了这种东西,但我对如何在 > 0.16 中实现它一无所知。
更新:
我已经按照 https://hackage.haskell.org/package/shake-0.17.3/docs/Development-Shake-Rule.html
的指南尝试过这个
newtype Repo = Repo String
deriving (Show, Eq, Hashable, Binary, NFData)
newtype Tag = Tag String
deriving (Show, Eq, Hashable, Binary, NFData)
newtype SHA256 = SHA256 String
deriving (Show, Eq, Hashable, Binary, NFData)
newtype Image = Image (Repo,Tag)
deriving (Show, Eq, Hashable, Binary, NFData)
type instance RuleResult Image = SHA256
data ImageRule = ImageRule Image (Action ())
imageRule :: (Repo, Tag) -> Action () -> Rules ()
imageRule k a = addUserRule $ ImageRule (Image k) a
needImage :: (Repo,Tag) -> Action SHA256
needImage = apply1 . Image
toBytes :: String -> BS.ByteString
toBytes = encodeUtf8 . Text.pack
fromBytes :: BS.ByteString -> String
fromBytes = Text.unpack . decodeUtf8
addBuiltinDockerRule :: Rules ()
addBuiltinDockerRule = addBuiltinRule noLint imageIdentity run
where
imageIdentity _ (SHA256 v) = toBytes v
imageSha (Image (Repo r,Tag t)) = do
Stdout out <- cmd "docker" [ "images", "--no-trunc", "-q", r <> ":" <> t ]
pure $ BS.unpack out
run :: BuiltinRun Image SHA256
run key old mode = do
current <- imageSha key
liftIO $ putStrLn ("current:" <> show current)
if mode == RunDependenciesSame && fmap BS.unpack old == Just current then
return $ RunResult ChangedNothing (BS.pack current) (SHA256 $ fromBytes $ BS.pack current)
else do
(_, act) <- getUserRuleOne key (const Nothing) $ \(ImageRule k act) -> if k == key then Just act else Nothing
act
current <- imageSha key
return $ RunResult ChangedRecomputeDiff (BS.pack current) (SHA256 $ fromBytes $ BS.pack current)
然后在 Build.hs
文件中使用它:
main :: IO ()
main = shakeArgs options $ do
addBuiltinDockerRule
want [ ".haskell.img" ]
imageRule (Repo "haskell", Tag "latest") $ do
need [ "docker/haskell/Dockerfile" ]
cmd "docker" [ "build", "-t", "haskell:latest", "-f", "docker/haskell/Dockerfile" ]
".haskell.img" %> \ fp -> do
needImage (Repo "haskell", Tag "latest")
Stdout out <- cmd "docker" [ "images", "--no-trunc", "-q", "haskell:latest" ]
writeFile' fp out
这似乎可行,但一个缺点是无法 want
图像:我必须添加文件规则才能使其正常工作。
因此建议的解决方案有效。可以添加一个 "phony" 目标以确保图像是按需构建的:
"haskell.img" ~> void (needImage "haskell")
我有一个 shake 构建(版本 0.16.4),它从 Dockerfile
和其他支持文件中构建了很多 docker 图像。我想将所有这些构建在单个 "rule" 中,其输出将是 docker 图像。我已经阅读 How to define a timer rule in Shake 关于 shake 中的自定义规则,但这并没有解释如何定义自己的 output。
我想表达一下
Image "foo" "latest" %> \ img -> do
need [ ... ]
buildDockerImage "docker/foo" img
Image "bar" "latest" %> \ img ->
needImage "foo" "latest"
...
然后让抖动跟踪图像作为依赖项。我已经在旧版本的 shake 中实现了这种东西,但我对如何在 > 0.16 中实现它一无所知。
更新:
我已经按照 https://hackage.haskell.org/package/shake-0.17.3/docs/Development-Shake-Rule.html
的指南尝试过这个newtype Repo = Repo String
deriving (Show, Eq, Hashable, Binary, NFData)
newtype Tag = Tag String
deriving (Show, Eq, Hashable, Binary, NFData)
newtype SHA256 = SHA256 String
deriving (Show, Eq, Hashable, Binary, NFData)
newtype Image = Image (Repo,Tag)
deriving (Show, Eq, Hashable, Binary, NFData)
type instance RuleResult Image = SHA256
data ImageRule = ImageRule Image (Action ())
imageRule :: (Repo, Tag) -> Action () -> Rules ()
imageRule k a = addUserRule $ ImageRule (Image k) a
needImage :: (Repo,Tag) -> Action SHA256
needImage = apply1 . Image
toBytes :: String -> BS.ByteString
toBytes = encodeUtf8 . Text.pack
fromBytes :: BS.ByteString -> String
fromBytes = Text.unpack . decodeUtf8
addBuiltinDockerRule :: Rules ()
addBuiltinDockerRule = addBuiltinRule noLint imageIdentity run
where
imageIdentity _ (SHA256 v) = toBytes v
imageSha (Image (Repo r,Tag t)) = do
Stdout out <- cmd "docker" [ "images", "--no-trunc", "-q", r <> ":" <> t ]
pure $ BS.unpack out
run :: BuiltinRun Image SHA256
run key old mode = do
current <- imageSha key
liftIO $ putStrLn ("current:" <> show current)
if mode == RunDependenciesSame && fmap BS.unpack old == Just current then
return $ RunResult ChangedNothing (BS.pack current) (SHA256 $ fromBytes $ BS.pack current)
else do
(_, act) <- getUserRuleOne key (const Nothing) $ \(ImageRule k act) -> if k == key then Just act else Nothing
act
current <- imageSha key
return $ RunResult ChangedRecomputeDiff (BS.pack current) (SHA256 $ fromBytes $ BS.pack current)
然后在 Build.hs
文件中使用它:
main :: IO ()
main = shakeArgs options $ do
addBuiltinDockerRule
want [ ".haskell.img" ]
imageRule (Repo "haskell", Tag "latest") $ do
need [ "docker/haskell/Dockerfile" ]
cmd "docker" [ "build", "-t", "haskell:latest", "-f", "docker/haskell/Dockerfile" ]
".haskell.img" %> \ fp -> do
needImage (Repo "haskell", Tag "latest")
Stdout out <- cmd "docker" [ "images", "--no-trunc", "-q", "haskell:latest" ]
writeFile' fp out
这似乎可行,但一个缺点是无法 want
图像:我必须添加文件规则才能使其正常工作。
因此建议的解决方案有效。可以添加一个 "phony" 目标以确保图像是按需构建的:
"haskell.img" ~> void (needImage "haskell")