Setting up a custom name of the WORKDIR to better document which exercise the user is working on
/google/trainings/haskell-101/00_setup
Properly implement a better Docker Cache for the haskell dependencies to avoid re-evaluating/downloading of the haskell dependencies when running stack run
Since the execution was placed in the container level, the dependencies were fetched at every execution
Added a deps Makefile task to be executed
Documenting the way to execute a terminal from docker-compose
That way, users learning haskell can execute the commands internally to the image
Allow users to solve the exercises from within a docker container
vim is now installed in the Docker image
NOTE: This is a solution only for haskell_101. I can submit an additional PR for haskell_202, with more generalizations, if this PR gets to be merged.
Another important point is when debugging, users can provide better logs for debugging what's going, which training they are doing, etc...
$ docker-compose up --build 03_lists
...
...
03_lists_1 | Installing executable solution in /google/trainings/haskell-101/03_lists/.stack-work/install/x86_64-linux/b75127df98e825dd26b7ce71e8ebbb670312dcae0b6d352496233a58a9f2a774/8.10.7/bin
03_lists_1 | null [] !! error: SOMETHING IS NOT IMPLEMENTED!
03_lists_1 | null [8,0,6] codelab: src/Codelab.hs:40:1-23: Non-exhaustive patterns in function null
03_lists_1 |
03_lists_1 | make: *** [Makefile:28: run] Error 1
03_lists_1 | make: Leaving directory '/google/trainings/haskell-101/03_lists'
codelab_03_lists_1 exited with code 2
As the underlying testing "framework" built in haskell explicitly added to get colored test results
Without them, that may also be a problem for some (me included)
β‘ Performance improvements π³
Created a single Makefile from a copy of setup, made it pull dependencies. That way, it's simpler for users to just run the docker container without having to re-run the entire process over and over again. Instead, taking advantage of the docker caching system by declaring a new layer in the Dockerfile to call the dependencies only.
All the time running the current code the build pulls everything over and over again. That's just too much after a while. We have 2 options:
Create a base docker image for everything
Reuse the same Dockerfile for the same docker image
Updating the Makefile with a new task to get the dependencies
Run the dependencies for each of them
Since dependencies don't change often, the docker image cache works perfectly to just pull the same dependencies for codecolab's functions and the execution is left as is. This time, faster as it takes advantage of the dependencies already built into the docker image instead of the docker container (that is, the current version).
π Documented the way to run terminal from docker-compose
Change the settings of docker-compose to include the cli-mode
$ git --no-pager diff docker-compose.yml
diff --git a/haskell_101/codelab/docker-compose.yml b/haskell_101/codelab/docker-compose.yml
index 4e6bb17..f87451f 100644
--- a/haskell_101/codelab/docker-compose.yml
+++ b/haskell_101/codelab/docker-compose.yml
@@ -53,8 +53,8 @@ services:
03_lists:
<<: [ *generic-haskell-runtime ]
# You can run in CLI mode with "docker-compose run 03_lists". Un-comment the following line and comment the "command" instruction below
- #<<: [ *docker-cli-mode ]
- command: make -C 03_lists
+ <<: [ *docker-cli-mode ]
+ #command: make -C 03_lists
04_abstractions:
Then run a container instead of up a container
You can edit a file using vim
$ docker-compose run 03_lists
Creating codelab_03_lists_run ... done
root@f410c7d1db9e:/google/trainings/haskell-101#
root@f410c7d1db9e:/google/trainings/haskell-101# ghci
GHCi, version 8.10.7: https://www.haskell.org/ghc/ :? for help
Prelude>
Leaving GHCi.
root@f410c7d1db9e:/google/trainings/haskell-101/01_functions# vim src/Codelab.hs
root@f410c7d1db9e:/google/trainings/haskell-101/01_functions# exit
exit
root@f410c7d1db9e:/google/trainings/haskell-101# exit
exit
π Docker Image: Build with Cached Dependencies
Note that only the first project shows a full resolution of the dependencies at step ls -d */ | awk '{ print $1 }' | xargs -I {} make -C {} deps
The execution of the dependency resolution was added to a consolidated Makefile in the root of the dir.
π Faster solution: Docker Containers only compile and run binaries
Since stack dependencies are resolved at docker image build-time, the process that executes stack run runs faster without pulling dependencies at every code change.
This is a reflection of the line COPY . . that is originally used in Dockerfile
$ docker-compose up 00_setup
Starting codelab_00_setup_1 ... done
Attaching to codelab_00_setup_1
00_setup_1 | make: Entering directory '/google/trainings/haskell-101/00_setup'
00_setup_1 | ============================================
00_setup_1 |
00_setup_1 | Haskell toolchain is installed! All is good.
00_setup_1 |
00_setup_1 | ============================================
00_setup_1 | make: Leaving directory '/google/trainings/haskell-101/00_setup'
codelab_00_setup_1 exited with code 0
All the dependencies were fetched during the docker image build
We don't see the previous download of the dependencies anymore
Proved by Docker's cache system
Logs show CACHED for every entry to the areas when it is executed
Forcing the rebuild will NOT pull the dependencies again
π π Logs with personal Haskell image working
I built haskell manually and it's working registry.gitlab.com/supercash/core/haskell-stack-base:stack-2.7.3_haskell-8.10.7_13057207-master
$ docker-compose up --build 01_functions
Building 01_functions
[+] Building 0.8s (18/18) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 37B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> resolve image config for docker.io/docker/dockerfile:1.2 0.4s
=> CACHED docker-image://docker.io/docker/dockerfile:1.2@sha256:e2a8561e419ab1ba6b2fe6cbdf49fd92b95912df1cf7d313c3e2230a333fdbcc 0.0s
=> [internal] load metadata for registry.gitlab.com/supercash/core/haskell-stack-base:stack-2.7.3_haskell-8.10.7_13057207-master 0.0s
=> [internal] load metadata for docker.io/library/alpine:latest 0.0s
=> [stage-1 1/7] FROM registry.gitlab.com/supercash/core/haskell-stack-base:stack-2.7.3_haskell-8.10.7_13057207-master 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 19.81kB 0.0s
=> [dependencies 1/3] FROM docker.io/library/alpine 0.0s
=> CACHED [stage-1 2/7] WORKDIR /google/trainings/haskell-101 0.0s
=> CACHED [dependencies 2/3] WORKDIR /google/trainings/haskell/cabal 0.0s
=> CACHED [dependencies 3/3] RUN --mount=type=bind,target=/docker-context cd /docker-context/; find . -type f ( -iname *.cabal -o -iname *.yaml* ) 0.0s
=> CACHED [stage-1 3/7] COPY --from=dependencies /google/trainings/haskell/cabal . 0.0s
=> CACHED [stage-1 4/7] COPY Makefile . 0.0s
=> CACHED [stage-1 5/7] RUN ls -d */ | awk '{ print $1 }' | xargs -I {} cp $(pwd)/Makefile $(pwd)/{} 0.0s
=> CACHED [stage-1 6/7] RUN ls -d */ | awk '{ print $1 }' | xargs -I {} make -C {} deps 0.0s
=> CACHED [stage-1 7/7] COPY . . 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:c8aeca37c1f5d263cea5acfce7a94f9dad21d18459475d5ff7f44daac1e9d420 0.0s
=> => naming to docker.io/google/haskell-trainings 0.0s
Starting codelab_01_functions_1 ... done
Attaching to codelab_01_functions_1
01_functions_1 | make: Entering directory '/google/trainings/haskell-101/01_functions'
01_functions_1 | add 1 2 !! error: SOMETHING IS NOT IMPLEMENTED!
01_functions_1 | subtract 7 2 !! error: SOMETHING IS NOT IMPLEMENTED!
01_functions_1 | double 3 !! error: SOMETHING IS NOT IMPLEMENTED!
01_functions_1 | multiply 3 11 !! error: SOMETHING IS NOT IMPLEMENTED!
01_functions_1 | divide 9 2 !! error: SOMETHING IS NOT IMPLEMENTED!
01_functions_1 | divide 8 4 !! error: SOMETHING IS NOT IMPLEMENTED!
01_functions_1 | factorial 30 !! error: SOMETHING IS NOT IMPLEMENTED!
01_functions_1 | gcd 12 4 !! error: SOMETHING IS NOT IMPLEMENTED!
01_functions_1 | gcd 17 7 !! error: SOMETHING IS NOT IMPLEMENTED!
01_functions_1 | make: *** [Makefile:28: run] Error 1
01_functions_1 | make: Leaving directory '/google/trainings/haskell-101/01_functions'
codelab_01_functions_1 exited with code 2
βοΈ aws-cli@2.2.32 π aws-iam-authenticator@0.5.3
βΈοΈ kubectl@1.22.4 π kustomize@v4.3.0 π‘ helm@3.7.0 π½ argocd@2.2.0 βοΈ glooctl@1.9.0 π³ docker@20.10.11 π docker-compose@1.29.2
π€ AWS_PS1_PROFILE ποΈ π sa-east-1
π 1.21.2-eks-0389ca3 π arn:aws:eks:sa-east-1:806101772216:cluster/eks-ppd-prd-super-cash π± default
~/dev/github.com/marcellodesales/haskell-trainings/haskell_101/codelab on ξ feature/more-efficient-docker-compose-execution! π 01-11-2022 β10:27:44
$ docker-compose up --build 02_datatypes
Building 02_datatypes
[+] Building 1.0s (18/18) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 37B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> resolve image config for docker.io/docker/dockerfile:1.2 0.5s
=> CACHED docker-image://docker.io/docker/dockerfile:1.2@sha256:e2a8561e419ab1ba6b2fe6cbdf49fd92b95912df1cf7d313c3e2230a333fdbcc 0.0s
=> [internal] load metadata for registry.gitlab.com/supercash/core/haskell-stack-base:stack-2.7.3_haskell-8.10.7_13057207-master 0.0s
=> [internal] load metadata for docker.io/library/alpine:latest 0.0s
=> [stage-1 1/7] FROM registry.gitlab.com/supercash/core/haskell-stack-base:stack-2.7.3_haskell-8.10.7_13057207-master 0.0s
=> [dependencies 1/3] FROM docker.io/library/alpine 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 19.81kB 0.0s
=> CACHED [stage-1 2/7] WORKDIR /google/trainings/haskell-101 0.0s
=> CACHED [dependencies 2/3] WORKDIR /google/trainings/haskell/cabal 0.0s
=> CACHED [dependencies 3/3] RUN --mount=type=bind,target=/docker-context cd /docker-context/; find . -type f ( -iname *.cabal -o -iname *.yaml* ) 0.0s
=> CACHED [stage-1 3/7] COPY --from=dependencies /google/trainings/haskell/cabal . 0.0s
=> CACHED [stage-1 4/7] COPY Makefile . 0.0s
=> CACHED [stage-1 5/7] RUN ls -d */ | awk '{ print $1 }' | xargs -I {} cp $(pwd)/Makefile $(pwd)/{} 0.0s
=> CACHED [stage-1 6/7] RUN ls -d */ | awk '{ print $1 }' | xargs -I {} make -C {} deps 0.0s
=> CACHED [stage-1 7/7] COPY . . 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:c8aeca37c1f5d263cea5acfce7a94f9dad21d18459475d5ff7f44daac1e9d420 0.0s
=> => naming to docker.io/google/haskell-trainings 0.0s
Starting codelab_02_datatypes_1 ... done
Attaching to codelab_02_datatypes_1
02_datatypes_1 | make: Entering directory '/google/trainings/haskell-101/02_datatypes'
02_datatypes_1 | hours (Minutes 271) !! error: SOMETHING IS NOT IMPLEMENTED!
02_datatypes_1 | hours (Minutes 15) !! error: SOMETHING IS NOT IMPLEMENTED!
02_datatypes_1 | timeDistance (Minutes 15) (Minutes 25) !! error: SOMETHING IS NOT IMPLEMENTED!
02_datatypes_1 | timeDistance (Minutes 99) (Minutes 47) !! error: SOMETHING IS NOT IMPLEMENTED!
02_datatypes_1 | pointDistance (1, 1) (1, 3) !! error: SOMETHING IS NOT IMPLEMENTED!
02_datatypes_1 | pointDistance (3, 4) (0, 0) !! error: SOMETHING IS NOT IMPLEMENTED!
02_datatypes_1 | make: *** [Makefile:28: run] Error 1
02_datatypes_1 | make: Leaving directory '/google/trainings/haskell-101/02_datatypes'
codelab_02_datatypes_1 exited with code 2
π π Full logs of running all in parallel with haskell:8
NOTE: Test 06_rps_1 is blocking the container waiting for the user's input... While this might be part of the requirement, executing the tests in a CI environment would not work...
$ ls -d */ | awk -F/ '{ print $1 }' | xargs docker-compose up --build
Removing codelab_06_rps_1
Building 00_setup
[+] Building 1.9s (20/20) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 37B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> resolve image config for docker.io/docker/dockerfile:1.2 1.0s
=> [auth] docker/dockerfile:pull token for registry-1.docker.io 0.0s
=> CACHED docker-image://docker.io/docker/dockerfile:1.2@sha256:e2a8561e419ab1ba6b2fe6cbdf49fd92b95912df1cf7d313c3e2230a333fdbcc 0.0s
=> [internal] load metadata for docker.io/library/haskell:8.10.7 0.6s
=> [internal] load metadata for docker.io/library/alpine:latest 0.0s
=> [auth] library/haskell:pull token for registry-1.docker.io 0.0s
=> [stage-1 1/7] FROM docker.io/library/haskell:8.10.7@sha256:6b4948a36e40b66a9cd6bfc279df43958d1aebc67a3909ba0c521d1d1395d26f 0.0s
=> [dependencies 1/3] FROM docker.io/library/alpine 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 19.81kB 0.0s
=> CACHED [stage-1 2/7] WORKDIR /google/trainings/haskell 0.0s
=> CACHED [dependencies 2/3] WORKDIR /google/trainings/haskell/cabal 0.0s
=> CACHED [dependencies 3/3] RUN --mount=type=bind,target=/docker-context cd /docker-context/; find . -type f ( -iname *.cabal -o -iname *.yaml* ) 0.0s
=> CACHED [stage-1 3/7] COPY --from=dependencies /google/trainings/haskell/cabal . 0.0s
=> CACHED [stage-1 4/7] COPY Makefile . 0.0s
=> CACHED [stage-1 5/7] RUN ls -d */ | awk '{ print $1 }' | xargs -I {} cp $(pwd)/Makefile $(pwd)/{} 0.0s
=> CACHED [stage-1 6/7] RUN ls -d */ | awk '{ print $1 }' | xargs -I {} make -C {} deps 0.0s
=> CACHED [stage-1 7/7] COPY . . 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:ab52b886c38b3ae9a4f2fe1631d272bf11388d5b55c1d5b78b4b584e86085e6f 0.0s
=> => naming to docker.io/google/haskell-trainings 0.0s
Building 01_functions
[+] Building 0.8s (18/18) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 37B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> resolve image config for docker.io/docker/dockerfile:1.2 0.2s
=> CACHED docker-image://docker.io/docker/dockerfile:1.2@sha256:e2a8561e419ab1ba6b2fe6cbdf49fd92b95912df1cf7d313c3e2230a333fdbcc 0.0s
=> [internal] load metadata for docker.io/library/haskell:8.10.7 0.2s
=> [internal] load metadata for docker.io/library/alpine:latest 0.0s
=> [dependencies 1/3] FROM docker.io/library/alpine 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 19.81kB 0.0s
=> [stage-1 1/7] FROM docker.io/library/haskell:8.10.7@sha256:6b4948a36e40b66a9cd6bfc279df43958d1aebc67a3909ba0c521d1d1395d26f 0.0s
=> CACHED [stage-1 2/7] WORKDIR /google/trainings/haskell 0.0s
=> CACHED [dependencies 2/3] WORKDIR /google/trainings/haskell/cabal 0.0s
=> CACHED [dependencies 3/3] RUN --mount=type=bind,target=/docker-context cd /docker-context/; find . -type f ( -iname *.cabal -o -iname *.yaml* ) 0.0s
=> CACHED [stage-1 3/7] COPY --from=dependencies /google/trainings/haskell/cabal . 0.0s
=> CACHED [stage-1 4/7] COPY Makefile . 0.0s
=> CACHED [stage-1 5/7] RUN ls -d */ | awk '{ print $1 }' | xargs -I {} cp $(pwd)/Makefile $(pwd)/{} 0.0s
=> CACHED [stage-1 6/7] RUN ls -d */ | awk '{ print $1 }' | xargs -I {} make -C {} deps 0.0s
=> CACHED [stage-1 7/7] COPY . . 0.0s
=> exporting to image 0.1s
=> => exporting layers 0.0s
=> => writing image sha256:ab52b886c38b3ae9a4f2fe1631d272bf11388d5b55c1d5b78b4b584e86085e6f 0.1s
=> => naming to docker.io/google/haskell-trainings 0.0s
Building 02_datatypes
[+] Building 0.7s (18/18) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 37B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> resolve image config for docker.io/docker/dockerfile:1.2 0.2s
=> CACHED docker-image://docker.io/docker/dockerfile:1.2@sha256:e2a8561e419ab1ba6b2fe6cbdf49fd92b95912df1cf7d313c3e2230a333fdbcc 0.0s
=> [internal] load metadata for docker.io/library/haskell:8.10.7 0.2s
=> [internal] load metadata for docker.io/library/alpine:latest 0.0s
=> [dependencies 1/3] FROM docker.io/library/alpine 0.0s
=> [stage-1 1/7] FROM docker.io/library/haskell:8.10.7@sha256:6b4948a36e40b66a9cd6bfc279df43958d1aebc67a3909ba0c521d1d1395d26f 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 19.81kB 0.0s
=> CACHED [stage-1 2/7] WORKDIR /google/trainings/haskell 0.0s
=> CACHED [dependencies 2/3] WORKDIR /google/trainings/haskell/cabal 0.0s
=> CACHED [dependencies 3/3] RUN --mount=type=bind,target=/docker-context cd /docker-context/; find . -type f ( -iname *.cabal -o -iname *.yaml* ) 0.0s
=> CACHED [stage-1 3/7] COPY --from=dependencies /google/trainings/haskell/cabal . 0.0s
=> CACHED [stage-1 4/7] COPY Makefile . 0.0s
=> CACHED [stage-1 5/7] RUN ls -d */ | awk '{ print $1 }' | xargs -I {} cp $(pwd)/Makefile $(pwd)/{} 0.0s
=> CACHED [stage-1 6/7] RUN ls -d */ | awk '{ print $1 }' | xargs -I {} make -C {} deps 0.0s
=> CACHED [stage-1 7/7] COPY . . 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:ab52b886c38b3ae9a4f2fe1631d272bf11388d5b55c1d5b78b4b584e86085e6f 0.0s
=> => naming to docker.io/google/haskell-trainings 0.0s
Building 03_lists
[+] Building 0.7s (18/18) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 37B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> resolve image config for docker.io/docker/dockerfile:1.2 0.2s
=> CACHED docker-image://docker.io/docker/dockerfile:1.2@sha256:e2a8561e419ab1ba6b2fe6cbdf49fd92b95912df1cf7d313c3e2230a333fdbcc 0.0s
=> [internal] load metadata for docker.io/library/haskell:8.10.7 0.2s
=> [internal] load metadata for docker.io/library/alpine:latest 0.0s
=> [dependencies 1/3] FROM docker.io/library/alpine 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 19.81kB 0.0s
=> [stage-1 1/7] FROM docker.io/library/haskell:8.10.7@sha256:6b4948a36e40b66a9cd6bfc279df43958d1aebc67a3909ba0c521d1d1395d26f 0.0s
=> CACHED [stage-1 2/7] WORKDIR /google/trainings/haskell 0.0s
=> CACHED [dependencies 2/3] WORKDIR /google/trainings/haskell/cabal 0.0s
=> CACHED [dependencies 3/3] RUN --mount=type=bind,target=/docker-context cd /docker-context/; find . -type f ( -iname *.cabal -o -iname *.yaml* ) 0.0s
=> CACHED [stage-1 3/7] COPY --from=dependencies /google/trainings/haskell/cabal . 0.0s
=> CACHED [stage-1 4/7] COPY Makefile . 0.0s
=> CACHED [stage-1 5/7] RUN ls -d */ | awk '{ print $1 }' | xargs -I {} cp $(pwd)/Makefile $(pwd)/{} 0.0s
=> CACHED [stage-1 6/7] RUN ls -d */ | awk '{ print $1 }' | xargs -I {} make -C {} deps 0.0s
=> CACHED [stage-1 7/7] COPY . . 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:ab52b886c38b3ae9a4f2fe1631d272bf11388d5b55c1d5b78b4b584e86085e6f 0.0s
=> => naming to docker.io/google/haskell-trainings 0.0s
Building 04_abstractions
[+] Building 0.8s (18/18) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 37B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> resolve image config for docker.io/docker/dockerfile:1.2 0.2s
=> CACHED docker-image://docker.io/docker/dockerfile:1.2@sha256:e2a8561e419ab1ba6b2fe6cbdf49fd92b95912df1cf7d313c3e2230a333fdbcc 0.0s
=> [internal] load metadata for docker.io/library/haskell:8.10.7 0.2s
=> [internal] load metadata for docker.io/library/alpine:latest 0.0s
=> [stage-1 1/7] FROM docker.io/library/haskell:8.10.7@sha256:6b4948a36e40b66a9cd6bfc279df43958d1aebc67a3909ba0c521d1d1395d26f 0.0s
=> [dependencies 1/3] FROM docker.io/library/alpine 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 19.81kB 0.0s
=> CACHED [stage-1 2/7] WORKDIR /google/trainings/haskell 0.0s
=> CACHED [dependencies 2/3] WORKDIR /google/trainings/haskell/cabal 0.0s
=> CACHED [dependencies 3/3] RUN --mount=type=bind,target=/docker-context cd /docker-context/; find . -type f ( -iname *.cabal -o -iname *.yaml* ) 0.0s
=> CACHED [stage-1 3/7] COPY --from=dependencies /google/trainings/haskell/cabal . 0.0s
=> CACHED [stage-1 4/7] COPY Makefile . 0.0s
=> CACHED [stage-1 5/7] RUN ls -d */ | awk '{ print $1 }' | xargs -I {} cp $(pwd)/Makefile $(pwd)/{} 0.0s
=> CACHED [stage-1 6/7] RUN ls -d */ | awk '{ print $1 }' | xargs -I {} make -C {} deps 0.0s
=> CACHED [stage-1 7/7] COPY . . 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:ab52b886c38b3ae9a4f2fe1631d272bf11388d5b55c1d5b78b4b584e86085e6f 0.0s
=> => naming to docker.io/google/haskell-trainings 0.0s
Building 05_maybe
[+] Building 0.7s (18/18) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 37B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> resolve image config for docker.io/docker/dockerfile:1.2 0.2s
=> CACHED docker-image://docker.io/docker/dockerfile:1.2@sha256:e2a8561e419ab1ba6b2fe6cbdf49fd92b95912df1cf7d313c3e2230a333fdbcc 0.0s
=> [internal] load metadata for docker.io/library/haskell:8.10.7 0.2s
=> [internal] load metadata for docker.io/library/alpine:latest 0.0s
=> [dependencies 1/3] FROM docker.io/library/alpine 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 19.81kB 0.0s
=> [stage-1 1/7] FROM docker.io/library/haskell:8.10.7@sha256:6b4948a36e40b66a9cd6bfc279df43958d1aebc67a3909ba0c521d1d1395d26f 0.0s
=> CACHED [stage-1 2/7] WORKDIR /google/trainings/haskell 0.0s
=> CACHED [dependencies 2/3] WORKDIR /google/trainings/haskell/cabal 0.0s
=> CACHED [dependencies 3/3] RUN --mount=type=bind,target=/docker-context cd /docker-context/; find . -type f ( -iname *.cabal -o -iname *.yaml* ) 0.0s
=> CACHED [stage-1 3/7] COPY --from=dependencies /google/trainings/haskell/cabal . 0.0s
=> CACHED [stage-1 4/7] COPY Makefile . 0.0s
=> CACHED [stage-1 5/7] RUN ls -d */ | awk '{ print $1 }' | xargs -I {} cp $(pwd)/Makefile $(pwd)/{} 0.0s
=> CACHED [stage-1 6/7] RUN ls -d */ | awk '{ print $1 }' | xargs -I {} make -C {} deps 0.0s
=> CACHED [stage-1 7/7] COPY . . 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:ab52b886c38b3ae9a4f2fe1631d272bf11388d5b55c1d5b78b4b584e86085e6f 0.0s
=> => naming to docker.io/google/haskell-trainings 0.0s
Building 06_rps
[+] Building 0.7s (18/18) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 37B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> resolve image config for docker.io/docker/dockerfile:1.2 0.2s
=> CACHED docker-image://docker.io/docker/dockerfile:1.2@sha256:e2a8561e419ab1ba6b2fe6cbdf49fd92b95912df1cf7d313c3e2230a333fdbcc 0.0s
=> [internal] load metadata for docker.io/library/alpine:latest 0.0s
=> [internal] load metadata for docker.io/library/haskell:8.10.7 0.2s
=> [internal] load build context 0.0s
=> => transferring context: 19.81kB 0.0s
=> [dependencies 1/3] FROM docker.io/library/alpine 0.0s
=> [stage-1 1/7] FROM docker.io/library/haskell:8.10.7@sha256:6b4948a36e40b66a9cd6bfc279df43958d1aebc67a3909ba0c521d1d1395d26f 0.0s
=> CACHED [stage-1 2/7] WORKDIR /google/trainings/haskell 0.0s
=> CACHED [dependencies 2/3] WORKDIR /google/trainings/haskell/cabal 0.0s
=> CACHED [dependencies 3/3] RUN --mount=type=bind,target=/docker-context cd /docker-context/; find . -type f ( -iname *.cabal -o -iname *.yaml* ) 0.0s
=> CACHED [stage-1 3/7] COPY --from=dependencies /google/trainings/haskell/cabal . 0.0s
=> CACHED [stage-1 4/7] COPY Makefile . 0.0s
=> CACHED [stage-1 5/7] RUN ls -d */ | awk '{ print $1 }' | xargs -I {} cp $(pwd)/Makefile $(pwd)/{} 0.0s
=> CACHED [stage-1 6/7] RUN ls -d */ | awk '{ print $1 }' | xargs -I {} make -C {} deps 0.0s
=> CACHED [stage-1 7/7] COPY . . 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:ab52b886c38b3ae9a4f2fe1631d272bf11388d5b55c1d5b78b4b584e86085e6f 0.0s
=> => naming to docker.io/google/haskell-trainings 0.0s
Starting codelab_01_functions_1 ... done
Recreating 7b362282ef91_codelab_06_rps_1 ... done
Starting codelab_02_datatypes_1 ... done
Recreating codelab_05_maybe_1 ... done
Recreating codelab_00_setup_1 ... done
Recreating codelab_04_abstractions_1 ... done
Starting codelab_03_lists_1 ... done
Attaching to codelab_01_functions_1, codelab_03_lists_1, codelab_02_datatypes_1, codelab_06_rps_1, codelab_00_setup_1, codelab_05_maybe_1, codelab_04_abstractions_1
01_functions_1 | make: Entering directory '/google/trainings/haskell/01_functions'
01_functions_1 | InvalidAbsFile "/.ghcup/ghc/8.10.7/lib/ghc-8.10.7/lib/../lib/x86_64-linux-ghc-8.10.7/rts-1.0.1/include/ghcversion.h"
01_functions_1 | make: *** [Makefile:28: run] Error 1
01_functions_1 | make: Leaving directory '/google/trainings/haskell/01_functions'
00_setup_1 | make: Entering directory '/google/trainings/haskell/00_setup'
02_datatypes_1 | make: Entering directory '/google/trainings/haskell/02_datatypes'
04_abstractions_1 | make: Entering directory '/google/trainings/haskell/04_abstractions'
03_lists_1 | make: Entering directory '/google/trainings/haskell/03_lists'
05_maybe_1 | make: Entering directory '/google/trainings/haskell/05_maybe'
06_rps_1 | make: Entering directory '/google/trainings/haskell/06_rps'
codelab_01_functions_1 exited with code 2
03_lists_1 | null [] !! error: SOMETHING IS NOT IMPLEMENTED!
03_lists_1 | null [8,0,6] !! error: SOMETHING IS NOT IMPLEMENTED!
03_lists_1 | head [8,0,6] !! error: SOMETHING IS NOT IMPLEMENTED!
03_lists_1 | tail [8,0,6] !! error: SOMETHING IS NOT IMPLEMENTED!
03_lists_1 | length [] !! error: SOMETHING IS NOT IMPLEMENTED!
03_lists_1 | length [8,0,6] !! error: SOMETHING IS NOT IMPLEMENTED!
03_lists_1 | and [] !! error: SOMETHING IS NOT IMPLEMENTED!
03_lists_1 | and [True] !! error: SOMETHING IS NOT IMPLEMENTED!
03_lists_1 | and [False] !! error: SOMETHING IS NOT IMPLEMENTED!
03_lists_1 | and [True, True] !! error: SOMETHING IS NOT IMPLEMENTED!
03_lists_1 | and [True, False] !! error: SOMETHING IS NOT IMPLEMENTED!
03_lists_1 | and [False, True] !! error: SOMETHING IS NOT IMPLEMENTED!
03_lists_1 | and [False, False] !! error: SOMETHING IS NOT IMPLEMENTED!
03_lists_1 | and [True, True, True] !! error: SOMETHING IS NOT IMPLEMENTED!
03_lists_1 | or [] !! error: SOMETHING IS NOT IMPLEMENTED!
03_lists_1 | or [True] !! error: SOMETHING IS NOT IMPLEMENTED!
03_lists_1 | or [False] !! error: SOMETHING IS NOT IMPLEMENTED!
03_lists_1 | or [True, True] !! error: SOMETHING IS NOT IMPLEMENTED!
03_lists_1 | or [True, False] !! error: SOMETHING IS NOT IMPLEMENTED!
03_lists_1 | or [False, True] !! error: SOMETHING IS NOT IMPLEMENTED!
03_lists_1 | or [False, False] !! error: SOMETHING IS NOT IMPLEMENTED!
03_lists_1 | or [False, False, True] !! error: SOMETHING IS NOT IMPLEMENTED!
03_lists_1 | [8,0] ++ [ ] !! error: SOMETHING IS NOT IMPLEMENTED!
03_lists_1 | [ ] ++ [6,4] !! error: SOMETHING IS NOT IMPLEMENTED!
03_lists_1 | [8,0] ++ [6,4] !! error: SOMETHING IS NOT IMPLEMENTED!
03_lists_1 | make: *** [Makefile:28: run] Error 1
03_lists_1 | make: Leaving directory '/google/trainings/haskell/03_lists'
codelab_03_lists_1 exited with code 2
02_datatypes_1 | InvalidAbsFile "/.ghcup/ghc/8.10.7/lib/ghc-8.10.7/lib/../lib/x86_64-linux-ghc-8.10.7/rts-1.0.1/include/ghcversion.h"
02_datatypes_1 | make: *** [Makefile:28: run] Error 1
02_datatypes_1 | make: Leaving directory '/google/trainings/haskell/02_datatypes'
06_rps_1 | Building all executables for `codelab' once. After a successful build of all of them, only specified executables will be rebuilt.
06_rps_1 | codelab> configure (exe)
00_setup_1 | codelab> configure (exe)
codelab_02_datatypes_1 exited with code 2
05_maybe_1 | Building all executables for `codelab' once. After a successful build of all of them, only specified executables will be rebuilt.
05_maybe_1 | codelab> configure (exe)
04_abstractions_1 | Building all executables for `codelab' once. After a successful build of all of them, only specified executables will be rebuilt.
04_abstractions_1 | codelab> configure (exe)
06_rps_1 | Configuring codelab-0.1.0.0...
00_setup_1 | Configuring codelab-0.1.0.0...
05_maybe_1 | Configuring codelab-0.1.0.0...
04_abstractions_1 | Configuring codelab-0.1.0.0...
06_rps_1 | codelab> build (exe)
00_setup_1 | codelab> build (exe)
06_rps_1 | Preprocessing executable 'codelab' for codelab-0.1.0.0..
06_rps_1 | Building executable 'codelab' for codelab-0.1.0.0..
05_maybe_1 | codelab> build (exe)
05_maybe_1 | Preprocessing executable 'codelab' for codelab-0.1.0.0..
05_maybe_1 | Building executable 'codelab' for codelab-0.1.0.0..
00_setup_1 | Preprocessing executable 'codelab' for codelab-0.1.0.0..
00_setup_1 | Building executable 'codelab' for codelab-0.1.0.0..
04_abstractions_1 | codelab> build (exe)
06_rps_1 | [1 of 3] Compiling Internal
04_abstractions_1 | Preprocessing executable 'codelab' for codelab-0.1.0.0..
04_abstractions_1 | Building executable 'codelab' for codelab-0.1.0.0..
05_maybe_1 | [1 of 3] Compiling Internal
00_setup_1 | [1 of 1] Compiling Main [Prelude changed]
04_abstractions_1 | [1 of 3] Compiling Internal
00_setup_1 | Linking .stack-work/dist/x86_64-linux/Cabal-3.2.1.0/build/codelab/codelab ...
06_rps_1 | [2 of 3] Compiling Codelab
05_maybe_1 | [2 of 3] Compiling Codelab
05_maybe_1 | [3 of 3] Compiling Main
04_abstractions_1 | [2 of 3] Compiling Codelab
04_abstractions_1 | [3 of 3] Compiling Main
06_rps_1 | [3 of 3] Compiling Main
05_maybe_1 | Linking .stack-work/dist/x86_64-linux/Cabal-3.2.1.0/build/codelab/codelab ...
04_abstractions_1 | Linking .stack-work/dist/x86_64-linux/Cabal-3.2.1.0/build/codelab/codelab ...
00_setup_1 | codelab> copy/register
00_setup_1 | Installing executable codelab in /google/trainings/haskell/00_setup/.stack-work/install/x86_64-linux/918a7a91b3f61592c6866bfa024bf1b0d9f5e73cebb23fd806ab595092ce6902/8.10.7/bin
00_setup_1 | Installing executable solution in /google/trainings/haskell/00_setup/.stack-work/install/x86_64-linux/918a7a91b3f61592c6866bfa024bf1b0d9f5e73cebb23fd806ab595092ce6902/8.10.7/bin
00_setup_1 | ============================================
00_setup_1 |
00_setup_1 | Haskell toolchain is installed! All is good.
00_setup_1 |
00_setup_1 | ============================================
00_setup_1 | make: Leaving directory '/google/trainings/haskell/00_setup'
06_rps_1 | Linking .stack-work/dist/x86_64-linux/Cabal-3.2.1.0/build/codelab/codelab ...
codelab_00_setup_1 exited with code 0
05_maybe_1 | Preprocessing executable 'solution' for codelab-0.1.0.0..
05_maybe_1 | Building executable 'solution' for codelab-0.1.0.0..
04_abstractions_1 | Preprocessing executable 'solution' for codelab-0.1.0.0..
04_abstractions_1 | Building executable 'solution' for codelab-0.1.0.0..
05_maybe_1 | [1 of 3] Compiling Internal
04_abstractions_1 | [1 of 3] Compiling Internal
06_rps_1 | Preprocessing executable 'solution' for codelab-0.1.0.0..
06_rps_1 | Building executable 'solution' for codelab-0.1.0.0..
06_rps_1 | [1 of 3] Compiling Internal
05_maybe_1 | [2 of 3] Compiling Solution
04_abstractions_1 | [2 of 3] Compiling Solution
05_maybe_1 | [3 of 3] Compiling Main
04_abstractions_1 | [3 of 3] Compiling Main
06_rps_1 | [2 of 3] Compiling Solution
05_maybe_1 | Linking .stack-work/dist/x86_64-linux/Cabal-3.2.1.0/build/solution/solution ...
04_abstractions_1 | Linking .stack-work/dist/x86_64-linux/Cabal-3.2.1.0/build/solution/solution ...
06_rps_1 | [3 of 3] Compiling Main
04_abstractions_1 | codelab> copy/register
05_maybe_1 | codelab> copy/register
04_abstractions_1 | Installing executable codelab in /google/trainings/haskell/04_abstractions/.stack-work/install/x86_64-linux/918a7a91b3f61592c6866bfa024bf1b0d9f5e73cebb23fd806ab595092ce6902/8.10.7/bin
04_abstractions_1 | Installing executable solution in /google/trainings/haskell/04_abstractions/.stack-work/install/x86_64-linux/918a7a91b3f61592c6866bfa024bf1b0d9f5e73cebb23fd806ab595092ce6902/8.10.7/bin
05_maybe_1 | Installing executable codelab in /google/trainings/haskell/05_maybe/.stack-work/install/x86_64-linux/918a7a91b3f61592c6866bfa024bf1b0d9f5e73cebb23fd806ab595092ce6902/8.10.7/bin
05_maybe_1 | Installing executable solution in /google/trainings/haskell/05_maybe/.stack-work/install/x86_64-linux/918a7a91b3f61592c6866bfa024bf1b0d9f5e73cebb23fd806ab595092ce6902/8.10.7/bin
04_abstractions_1 | map (+1) [] !! error: SOMETHING IS NOT IMPLEMENTED!
04_abstractions_1 | map (+1) [8,0,6,4] !! error: SOMETHING IS NOT IMPLEMENTED!
04_abstractions_1 | filter (>5) [] !! error: SOMETHING IS NOT IMPLEMENTED!
04_abstractions_1 | filter (>5) [8,0,6,4] !! error: SOMETHING IS NOT IMPLEMENTED!
04_abstractions_1 | foldl (-) 1 [10] !! error: SOMETHING IS NOT IMPLEMENTED!
04_abstractions_1 | foldl (-) 0 [1,2,3,4] !! error: SOMETHING IS NOT IMPLEMENTED!
04_abstractions_1 | foldl (++) "_" ["A", "B", "C"] !! error: SOMETHING IS NOT IMPLEMENTED!
04_abstractions_1 | foldr (-) 1 [10] !! error: SOMETHING IS NOT IMPLEMENTED!
04_abstractions_1 | foldr (-) 0 [1,2,3,4] !! error: SOMETHING IS NOT IMPLEMENTED!
04_abstractions_1 | foldr (++) "_" ["A", "B", "C"] !! error: SOMETHING IS NOT IMPLEMENTED!
04_abstractions_1 | make: *** [Makefile:28: run] Error 1
04_abstractions_1 | make: Leaving directory '/google/trainings/haskell/04_abstractions'
05_maybe_1 | safeHead [] !! error: SOMETHING IS NOT IMPLEMENTED!
05_maybe_1 | safeHead [8,0,6] !! error: SOMETHING IS NOT IMPLEMENTED!
05_maybe_1 | isNothing (Just 42) !! error: SOMETHING IS NOT IMPLEMENTED!
05_maybe_1 | isNothing Nothing !! error: SOMETHING IS NOT IMPLEMENTED!
05_maybe_1 | fromMaybe 0 (Just 40) !! error: SOMETHING IS NOT IMPLEMENTED!
05_maybe_1 | fromMaybe 0 Nothing !! error: SOMETHING IS NOT IMPLEMENTED!
05_maybe_1 | maybe 0 (+2) (Just 40) !! error: SOMETHING IS NOT IMPLEMENTED!
05_maybe_1 | maybe 0 (+2) Nothing !! error: SOMETHING IS NOT IMPLEMENTED!
05_maybe_1 | make: *** [Makefile:28: run] Error 1
05_maybe_1 | make: Leaving directory '/google/trainings/haskell/05_maybe'
06_rps_1 | Linking .stack-work/dist/x86_64-linux/Cabal-3.2.1.0/build/solution/solution ...
codelab_04_abstractions_1 exited with code 2
codelab_05_maybe_1 exited with code 2
06_rps_1 | codelab> copy/register
06_rps_1 | Installing executable codelab in /google/trainings/haskell/06_rps/.stack-work/install/x86_64-linux/918a7a91b3f61592c6866bfa024bf1b0d9f5e73cebb23fd806ab595092ce6902/8.10.7/bin
06_rps_1 | Installing executable solution in /google/trainings/haskell/06_rps/.stack-work/install/x86_64-linux/918a7a91b3f61592c6866bfa024bf1b0d9f5e73cebb23fd806ab595092ce6902/8.10.7/bin
06_rps_1 | Welcome to Rock-Paper-Scissors!
06_rps_1 | -------------------------------
06_rps_1 | Each move is one of [Rock,Paper,Scissors]
π Improvements
WORKDIR
to better document which exercise the user is working on/google/trainings/haskell-101/00_setup
stack run
deps
Makefile task to be executedvim
is now installed in the Docker imageAnother important point is when debugging, users can provide better logs for debugging what's going, which training they are doing, etc...
π Bugfixes
π©Ή Preserved Container coloring -
when in docker-compose
β‘ Performance improvements π³
Created a single Makefile from a copy of setup, made it pull dependencies. That way, it's simpler for users to just run the docker container without having to re-run the entire process over and over again. Instead, taking advantage of the docker caching system by declaring a new layer in the
Dockerfile
to call the dependencies only.π© Inefficient runs
All the time running the current code the build pulls everything over and over again. That's just too much after a while. We have 2 options:
Dockerfile
for the same docker imageMakefile
with a new task to get the dependenciesSince dependencies don't change often, the docker image cache works perfectly to just pull the same dependencies for codecolab's functions and the execution is left as is. This time, faster as it takes advantage of the dependencies already built into the docker image instead of the docker container (that is, the current version).
π Documented the way to run terminal from docker-compose
run
a container instead ofup
a containerπ Docker Image: Build with Cached Dependencies
ls -d */ | awk '{ print $1 }' | xargs -I {} make -C {} deps
Makefile
in the root of the dir.CACHED
π Faster solution: Docker Containers only compile and run binaries
stack run
runs faster without pulling dependencies at every code change.COPY . .
that is originally used inDockerfile
CACHED
for every entry to the areas when it is executedπ π³ Docker image
haskell:8
abs problemabs
function...π π Logs with personal Haskell image working
π π Full logs of running all in parallel with
haskell:8