5

Dockerfile我有一个shake build(0.16.4版),它用s和其他支持文件构建了很多docker镜像。我想将所有这些构建在一个单一的“规则”中,其输出将是一个 docker 图像。我已经阅读了 How to define a timer rule in Shake about custom rules in Shake 但这并没有解释如何定义自己的输出

我想表达类似的东西

 Image "foo" "latest" %> \ img -> do
     need [ ... ]
     buildDockerImage "docker/foo" img

 Image "bar" "latest" %> \ img -> 
     needImage "foo" "latest"
     ...

然后将图像作为依赖项摇动跟踪。我已经在旧版本的抖动中实现了这种东西,但我对如何在 > 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:我必须添加一个带有文件的规则才能使其工作。

4

1 回答 1

1

因此,建议的解决方案有效。可以添加一个“假”目标以确保图像是按需构建的:

"haskell.img" ~> void (needImage "haskell")
于 2019-01-08T07:55:04.410 回答