@@ -21,9 +21,10 @@ module Docker.Client.Api (
21 , buildImageFromDockerfile
21 , buildImageFromDockerfile
22 -- * Other
22 -- * Other
23 , getDockerVersion
23 , getDockerVersion
26−import Control.Monad.Catch (MonadMask(..))
27+import Control.Monad.Catch (MonadMask (..))
27import Control.Monad.IO.Class
28import Control.Monad.IO.Class
28import Control.Monad.Reader (ask, lift)
29import Control.Monad.Reader (ask, lift)
29import Data.Aeson (FromJSON, eitherDecode')
30import Data.Aeson (FromJSON, eitherDecode')
@@ -31,10 +32,11 @@ import qualified Data.ByteString as BS
31import qualified Data.ByteString.Lazy as BSL
32import qualified Data.ByteString.Lazy as BSL
32import Data.Conduit (Sink)
33import Data.Conduit (Sink)
33import qualified Data.Conduit.Binary as Conduit
34import qualified Data.Conduit.Binary as Conduit
35+import qualified Data.Text as T
34import qualified Data.Text as Text
36import qualified Data.Text as Text
35−import Network.HTTP.Client (responseStatus)
37+import Network.HTTP.Client (responseStatus)
36−import Network.HTTP.Types (StdMethod (..))
38+import Network.HTTP.Types (StdMethod (..))
37−import System.Exit (ExitCode(..))
39+import System.Exit (ExitCode (..))
39import Docker.Client.Http
41import Docker.Client.Http
40import Docker.Client.Types
42import Docker.Client.Types
@@ -54,8 +56,8 @@ requestHelper' verb endpoint sink = do
54 return $ Left $ DockerInvalidRequest endpoint
56 return $ Left $ DockerInvalidRequest endpoint
55 Just request -> do
57 Just request -> do
56 -- JP: Do we need runResourceT?
58 -- JP: Do we need runResourceT?
57− -- lift $ NHS.httpSink request $ \response ->
59+ -- lift $ NHS.httpSink request $ \response ->
58− lift $ httpHandler request $ \response ->
60+ lift $ httpHandler request $ \response ->
59 -- Check status code.
61 -- Check status code.
60 let status = responseStatus response in
62 let status = responseStatus response in
61 case statusCodeToError endpoint status of
63 case statusCodeToError endpoint status of
@@ -149,21 +151,25 @@ inspectContainer cid = requestHelper GET (InspectContainerEndpoint cid) >>= pars
149-- See 'LogOpts' for options that you can pass and
151-- See 'LogOpts' for options that you can pass and
150-- 'defaultLogOpts' for sane defaults.
152-- 'defaultLogOpts' for sane defaults.
152−-- __NOTE__: Currently streaming logs is
153−-- not supported and this function will fetch the entire log that the
154+-- __NOTE__: his function will fetch the entire log that the
154-- container produced in the json-file on disk. Depending on the logging
155-- container produced in the json-file on disk. Depending on the logging
155-- setup of the process in your container this can be a significant amount
156-- setup of the process in your container this can be a significant amount
156-- which might block your application...so use with caution.
157-- which might block your application...so use with caution.
159+-- If you want to stream the logs from the container continuosly then use
160+-- 'getContainerLogsStream'
158−-- The recommended method is to use one of the other 'LogDriverType's available (like
162+-- __NOTE__: It's recommended to use one of the other 'LogDriverType's available (like
159-- syslog) for creating your containers.
163-- syslog) for creating your containers.
160getContainerLogs :: forall m. (MonadIO m, MonadMask m) => LogOpts -> ContainerID -> DockerT m (Either DockerError BSL.ByteString)
164getContainerLogs :: forall m. (MonadIO m, MonadMask m) => LogOpts -> ContainerID -> DockerT m (Either DockerError BSL.ByteString)
161getContainerLogs logopts cid = requestHelper GET (ContainerLogsEndpoint logopts False cid)
165getContainerLogs logopts cid = requestHelper GET (ContainerLogsEndpoint logopts False cid)
167+-- | Continuosly gets the container's logs as a stream. Uses conduit.
163getContainerLogsStream :: forall m b . (MonadIO m, MonadMask m) => LogOpts -> ContainerID -> Sink BS.ByteString m b -> DockerT m (Either DockerError b)
168getContainerLogsStream :: forall m b . (MonadIO m, MonadMask m) => LogOpts -> ContainerID -> Sink BS.ByteString m b -> DockerT m (Either DockerError b)
164−getContainerLogsStream logopts cid sink = requestHelper' GET (ContainerLogsEndpoint logopts True cid) sink
169+getContainerLogsStream logopts cid = requestHelper' GET (ContainerLogsEndpoint logopts True cid)
165-- JP: Should the second (follow) argument be True? XXX
170-- JP: Should the second (follow) argument be True? XXX
172+-- | Build an Image from a Dockerfile
167-- TODO: Add X-Registry-Config
173-- TODO: Add X-Registry-Config
168-- TODO: Add support for remote URLs to a Dockerfile
174-- TODO: Add support for remote URLs to a Dockerfile
169-- TODO: Clean up temp tar.gz file after the image is built
175-- TODO: Clean up temp tar.gz file after the image is built
@@ -171,5 +177,15 @@ buildImageFromDockerfile :: forall m. (MonadIO m, MonadMask m) => BuildOpts -> F
171buildImageFromDockerfile opts base = do
177buildImageFromDockerfile opts base = do
172 ctx <- makeBuildContext $ BuildContextRootDir base
178 ctx <- makeBuildContext $ BuildContextRootDir base
173 case ctx of
179 case ctx of
174− Left e -> return $ Left e
180+ Left e -> return $ Left e
175 Right c -> requestUnit POST (BuildImageEndpoint opts c)
181 Right c -> requestUnit POST (BuildImageEndpoint opts c)
183+-- | Pulls an image from Docker Hub (by default).
184+-- TODO: Add support for X-Registry-Auth and pulling from private docker
186+-- TODO: Implement importImage function that uses he same
187+-- CreateImageEndpoint but rather than pulling from docker hub it imports
188+-- the image from a tarball or a URL.
189+pullImage :: forall m b . (MonadIO m, MonadMask m) => T.Text -> Tag -> Sink BS.ByteString m b -> DockerT m (Either DockerError b)
190+pullImage name tag = requestHelper' POST (CreateImageEndpoint name tag Nothing)