#how to tag a container image after call build?
1 messages ยท Page 1 of 1 (latest)
@gritty oak are you looking to push the container as an OCI image to a registry? Or are you looking to load it into a Docker engine running your machine?
Assuming it's the latter: https://archive.docs.dagger.io/0.9/252029/load-images-local-docker-engine
if you want to push the tagged image to a container registry, you can use the publish method on the container type for that. More info here: https://docs.dagger.io/guides/457482/create-app-ci-module/#step-5-add-a-function-to-publish-the-application-image
im migrating my GHA pipeline to dagger. which is usual, 1. build - 2. test - 3. push. So in #1 step i build the container images as show and then on #2 i run a docker compose file which set the test env
how can i accomplish this with dagger?
You can do 1, 2, 3 all as part of the same Dagger pipeline ๐
do you have an example on how to do it @lofty torrent ? i know i can build the docker compose file by code using the sdk by i already have the .yaml file the thing is that it trust the images on step #1 to have certain tags lets say api:9asd87as and i cant find a way to do that part
Are you able to share the yaml file here?
And also the Dagger code you've already written (if any)
i was unable to write any. im kind of struggling to find doc on how to
No worries! That's why we're here ๐
Your language of choice is typescript?
Are you able to share the Dockerfile too?
That's a serious dockerfile!
So pre-Dagger, once the image is built, what would running the e2e test look like? Is there a particular command you'd run, or a particular section of the compose file I should look at?
the steps usually looks like
- docker compose up -d
- docker compose exec test composer behat
how do you aim compose at the right image tag, do you pass the tag an env variable to compose?
no, is just configure there.
โฆ
api:
image: snoutzone/ci
โฆ
test:
<<: *common
image: snoutzone/dev
โฆ
the build step tag the images as that so composer can use them
Ah I see, you just hardcode docker build -t snoutzone/dev
exactly
and thats what im trying to do now with dagger so composer can find those images
@wooden prairie I'm experimenting with Docker Compose compat in your docker module for this, is it known to work? ๐
@gritty oak so there are 2 possible ways to do this:
Option 1. Reimplement (parts of) the Docker Compose file, plus the glue commands to integrate build+compose-exec, as native Dagger calls. Almost everything maps one-to-one, so it's tedious but straightforward, and only needs to be done once. Let's say 50 lines of code fully loaded.
Option 2. Only implement the glue commands in Dagger, and use a Docker Compose compat module to just pass your compose project as an argument. Probably requires light editing of the Compose file, which may or may not be ready. This requires a working docker compose compat. I'm investigating.
it'll parse a docker-compose.yml and run them as services with c2c networking in an analogous way, not sure what you mean by compatibility or "work" beyond that ๐ - I have used it to run services though
by the looks of it, this pattern won't work, since it just does a From() when an image name is set, which will try to pull it from a registry. it'll work if you set build: <path> instead though
(code I'm referencing is here: https://github.com/vito/daggerverse/blob/9f66a3dc5a3687c0828e2499894a51315f998b5c/docker/compose.go#L116-L134)
@wooden prairie I tried dagger call -m docker compose --project . all up But it failed with "no ports to forward"
Also, can I run an individual service instead of all of them combined?
And, if the compose file defines dependencies between projects, will they work?
starting one services isn't implemented, but it should be easy to, since the dependencies are expressed as a DAG
Unfortunately service dependencies via docker networks aren't a DAG..
To my knowledge we haven't found a solution to that yet
it can be cyclic?
or i guess you're all just peers, and depends_on is just the dependency order, if you define it
ok i see what you mean here now #maintainers message
Yes exactly. Network dependency DAG is actually not statically defined anywhere, it's whatever hostnames each service decides to lookup at runtime
All services can connect to each other in the network namespace. N-to-N
i wonder if that could be implemented in a module 
technically all containers can already reach each other, it's just an addressing issue
An explicit DAG would work fine 99% of the time, but can't be generated from the compose file unless very disciplined about depends-on
you would need to 1) control the service bindings and 2) solve the chicken and egg problem of the current service api
if you require that compose file explicitly define the dag with depends_on, it could work
at least as an initial crutch until we figure out better magic
yeah, the file i use for testing uses depends_on, I've always used it so never thought about it: https://github.com/vito/daggerverse/blob/main/test/wordpress.yml
interesting topic. but definetly something that can block dagger adoption in some cases. maybe an interpreter that generates dagger code to conver compose file to dagger code could solve it
ok but getting back to the original question, there is no way to tag a container/image with dagger right? the dagger flow goes as container -> build -> use it as you want -> publish (this actually support tagging)
i got it right?
this post covers the current options: https://archive.docs.dagger.io/0.9/252029/load-images-local-docker-engine/
tl;dr you can either export to a local tarball or push to a locally running registry
you can also run an ephemeral docker engine in the container, then aim regular docker-composr at it. That works quite well actually, @gaunt gate did it for slim integration
I will try for you this weekend @gritty oak ๐
thanks a lot guys, awesome team
this is funny, because even though services are in fact N-to-N, if you use the depends_on clause in compose to define specify dependency, that gets modeled into a DAG. You can't have cycles using the depends_on attribute in compose
so, unless I'm missing something, if the compose project is based on the depends_on to hint it's services dependencies, that should work in Dagger without changes.
I guess this basically..
so if all services in compose are relaying in depends_on and build a DAG it can be done right? that said which module do you guys advice to try this, i mean load a compose file and try it?
so if all services in compose are relaying in depends_on and build a DAG it can be done right?
yes, that's correct. Seems like @lofty torrent has been playing with Alex's compose thing during the weekend (https://github.com/shykes/daggerverse/tree/c448f929b53be0f09eafe884cc77612a6d6fc7f9/docker-compose). I'd wait to see if he was able to get something running ๐
will take a pick into it
Hello! I am currently stuck on a weird dagger error, which prevents me from installing the docker module ๐ฆ
I figured I would start with the full compat option: embed a docker engine + docker-compose, get everything running. Then gradually refactor to make it more native & efficient
OK, I am unstuck!
@gritty oak @pale sphinx @wooden prairie taking a break for lunch, I have a basic POC that's not fully functional, but gives an idea of what "option 1" would look like:
dagger call -m github.com/shykes/daggerverse/sratch/bitgantter \
test-env --app index.docker.io/nginx \
terminal
--> This will setup a test environment with an ephemeral docker engine + docker-compose CLI, inject the given app container into the same engine, and set everything up to run docker-compose exec test ... against it
(in my example, I just point to nginx as a fake app container)
I intentionally don't handle the build, because that's easy to do. Will add to the complete demo after
To recap, there are 3 options:
- Run docker-compose in Dagger: most compatible, least efficient --> This is the one I'm prototyping
- Run a docker-compose compat module: intermediate
- Reimplement the compose file in code: least compatible, most efficient
In the terminal you can access $APP_IMAGE which is the ID of the injected container to test
It's not tagged yet, I'll take care of that after lunch break
FYI I'm pushing an update in the next few minutes ๐
OK here we go ๐
dagger call -m github.com/shykes/daggerverse/scratch/bitgantter@v0.2.1 \
test \
--app index.docker.io/nginx \
--command sh,-c,'curl http://app'
It takes longer to run than necessary, because of a temporary bug which causes the ephemeral docker engine to be re-started in between each client call. It works because the docker engine state is persisted in a cache volume. But still adds a little overhead
I took the approach of not supporting passing arbitrary docker-compose files to the funciton, like I originally did. That way, I can enforce a simple convention in the compose file. At the moment the convention is:
- There should be a service called
appusing imageapp, where the Dagger Function will inject the app container to be tested - There should be a service called
testusing imagetest, and executing something that never returns (so thatdocker-compose updoesn't fail
This basically makes the compose file an implementation detail of the test-env function. Later it could be refactored away entirely.
I also added a test-source function that takes a source directory as argument, rather than a container. It simply does a standard docker build, and passes the result to test.
Example building a remote repo:
dagger call -m github.com/shykes/daggerverse/scratch/bitgandtter@v0.2.1 \
test-source \
--source https://github.com/dagger/hello-dagger \
--command sh,-c,'curl http://app'
And building a local source checkout:
dagger call -m github.com/shykes/daggerverse/scratch/bitgandtter@v0.2.1 \
test-source \
--source . \
--command sh,-c,'curl http://app'
In all the commands above, you can pass a custom test container with --test-container
Thanks @lofty torrent saw the work there and its an starting point. But on my scenario i dont think its going to work. As you can see my testing env relies a lot on the compose file and all moving pieces (secrets, volumes, and so on). That said i think i know the path now and i can start building something around it. Will share if i manage to make it work
Is it specifically wrapping a whole docker engine that you think wouldn't work? Or something else in the way the functions are designed?
This is turning to be very educational for me btw ๐
yes i do thing that starting an ephemeral docker engine can help, at least easy the path. but i was tryionh to go the dag path you know
Yeah, honestly after going through the process of wrangling that docker integration, I kind of feel that it's easier to bite the bullet and convert to native Dagger code.
@here if i parse the docker compose file and i intend to create the same ecosystem using dagger api, which its going to be the best way? given that they must complain to networks, volumes, and so on?
I'd say you can start here with the code that @wooden prairie started: https://github.com/vito/dagger-compose. That already does most of the heavy lifting since it uses the same official Go library that docker compose uses internally
I'd say that most of the things are there, so it's mostly a matter of hooking your compose file and see what doesn't work
got you. my main stop holder is that im not a go developer so wont be able to tweak things. thanks will read whats in there
happy to help in whatever is not working. I'd say that in this case it's best to use Go since you can leverage in the existing docker code that parses the compose file
oh just to clarify, that repo was the precursor to https://github.com/vito/daggerverse/blob/9f66a3dc5a3687c0828e2499894a51315f998b5c/docker/compose.go which we mentioned previously
right! that has the latest code ๐
@wooden prairie we should merge our compose packages ๐
I kind of want to start an unofficial distro
just missing a silly name
I could bring back "stackbrew"
or "dagbrew"?
dagopedia
lol, yeah probably - i'd wager it makes more sense for you to own it ๐
of what? ๐
ah got it. yeah, i guess that's one downside to monorepos, don't think there's per-directory write permissions, at least not on GitHub
unless you just do PRs
in lieu of that, feel free to just scrap mine for parts, and I can delist/remove mine to consolidate
yes that will require PR and review from you guys, the symfony php community does similar with what they call flex packages
ok, i know i have ask this question before but here comes again. The main reason for asking again is that i dont completely understand the concepts of: pipeline and https://docs.dagger.io/api/reference/#definition-Service. So the question. If i want to implement something like compose, few services/containers sharing same network, which dag resources are recommended and why?
@lofty torrent @wooden prairie any advice?
Can you tell me more about how you're trying to use the Service primitive ? Are you trying to reimplement the stack from that docker compose file, in pure code?
exactly "Are you trying to reimplement the stack from that docker compose file, in pure code?" but i dont know which primitive to use, i was looking for arch concepts on the doc but cant find any. So if you can point me to which resources should i use. For example as docker compose i would like the containers to be isolated in their own network, volumes, etc
The general idea:
- For each service configuratin in the compose file, write a Dagger function that returns an equivalent
Container. - For each dependency in the compose file (
depends_on): add the dependency as an argument to the client container. The argument should be of typeService.
In Go:
// The 'db' service from compose file, ported to a function
func DB() *Container {
return dag.
Container().
From("postgres").
WithExposedPort(...).
WithBlaBlaBla()
}
// The 'api' service from compose file, ported to a function
func API(source *Directory, db *Service) *Container {
return dag.
Container().
From("php-server-image").
WithDirectory("/app", source).
WithBlaBlaBla().
WithServiceBinding("db", db)
}
I think I remember Python is your language of choice, sorry, my Python is quite rusty. But it all transposes 1-1 to Python code.
ok but i have few more questions:
- dont quite get db container build on first function can be pass as the db Service argument of the second one? so container == service? or something more needs to be done in the middle?
- calling the WithServiceBinding method is like the old link config in docker compose?
- There is any way to create a dedicated network for all this containers/services; like compose does? as you can see in my compose file some internal dns requires the ip to work
a service is an abstraction for a network endpoint: basically one or more ports that you can connect to from a container (by binding it).
Dagger has 2 underlying service implementations: container services (call Container.asService()). And host services, which are tunnels to endpoints running outside Dagger.
this means you can call Api() and pass it a dv service that is either running in another container run by dagger, OR outside dagger, and the Api function won't know the difference
better composition
yes it's very similar to old docker links (which I designed ironically)
cool. i think i got it. let me see where i can get it, having fun with this
@lofty torrent maybe you can take a look at this PoC https://github.com/wildbitca/daggerverse/tree/master/docker-compose and give me some feedback. Im just starting with dagger im sure there are better ways to do stuff or even i may be doing some of them the wrong way. That said its build in base of my personal requirements which is been able to bring a full/complex docker compose project and reutilize dag containers previously build from dockerfiles without pushing them to any registry