├── .gitignore ├── spec ├── spec_helper.cr └── hello_world_spec.cr ├── shard.yml ├── shard.lock ├── src └── main.cr ├── Dockerfile ├── d_dev ├── Makefile ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | lib/ 2 | out/ 3 | -------------------------------------------------------------------------------- /spec/spec_helper.cr: -------------------------------------------------------------------------------- 1 | require "spec" 2 | -------------------------------------------------------------------------------- /shard.yml: -------------------------------------------------------------------------------- 1 | name: my_app 2 | version: 0.1.0 3 | 4 | dependencies: 5 | idle-gc: 6 | github: compumike/idle-gc 7 | -------------------------------------------------------------------------------- /shard.lock: -------------------------------------------------------------------------------- 1 | version: 2.0 2 | shards: 3 | idle-gc: 4 | git: https://github.com/compumike/idle-gc.git 5 | version: 1.0.0 6 | 7 | -------------------------------------------------------------------------------- /spec/hello_world_spec.cr: -------------------------------------------------------------------------------- 1 | require "./spec_helper" 2 | 3 | describe "HelloWorld" do 4 | # Your tests go here 5 | it "asserts 2 + 2 = 4" do 6 | (2 + 2).should eq(4) 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /src/main.cr: -------------------------------------------------------------------------------- 1 | require "idle-gc" 2 | 3 | class MyApp 4 | def initialize 5 | IdleGC.start # Run garbage collection while idle 6 | end 7 | 8 | def main 9 | # Your code here. 10 | 10.times do |n| 11 | puts "(#{n}) Hello world! The current time is #{Time.utc.to_rfc3339(fraction_digits: 9)}" 12 | sleep(1.seconds) 13 | end 14 | end 15 | end 16 | 17 | MyApp.new.main 18 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM crystallang/crystal:1.17.1-alpine 2 | 3 | RUN apk --update --no-cache add \ 4 | bash \ 5 | ca-certificates \ 6 | tzdata 7 | 8 | WORKDIR /app/ 9 | 10 | COPY ./shard.yml ./shard.lock /app/ 11 | 12 | RUN shards install --frozen 13 | 14 | COPY ./ /app/ 15 | 16 | RUN make 17 | 18 | # If you want to avoid memory spikes due to loading debug symbols when an Exception fires, set CRYSTAL_LOAD_DEBUG_INFO=0. 19 | # See https://github.com/compumike/idle-gc#crystal_load_debug_info0 for more information. 20 | #ENV CRYSTAL_LOAD_DEBUG_INFO=0 21 | 22 | # We'll start you off with a bash shell, but you can have the docker image run your compiled binary directly if you wish. 23 | #CMD ["/app/out/my_app"] 24 | CMD ["/bin/bash"] 25 | -------------------------------------------------------------------------------- /d_dev: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | cd "$(dirname "$0")" 6 | 7 | # Replace this with whatever name you'd like to tag this image as. 8 | DOCKER_IMAGE="crystal-docker-quickstart-my_app" 9 | 10 | # Mount local directory for development convenience. 11 | DOCKER_VOLUME="-v `pwd`:/app" 12 | 13 | # Uncomment to expose a port if you're hosting a server. 14 | DOCKER_EXPOSE="" 15 | #DOCKER_EXPOSE="-p 3000:3000/tcp" 16 | 17 | # Uncomment if you'd like to pass external environment variables into the Docker container and therefore to your application. 18 | DOCKER_ENV="" 19 | #DOCKER_ENV="-e MY_ENV_KEY_EXAMPLE" 20 | 21 | DOCKER_ARGS="${DOCKER_VOLUME} ${DOCKER_EXPOSE} ${DOCKER_ENV}" 22 | 23 | DOCKER_BUILDKIT=1 docker build -t ${DOCKER_IMAGE} -f Dockerfile . 24 | 25 | exec docker run --rm -it ${DOCKER_ARGS} ${DOCKER_IMAGE} 26 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: out/my_app 2 | 3 | # CHOOSE ONE: 4 | # Add debugging symbols or not? Makes binaries larger, but can print useful backtraces. 5 | DEBUG=--debug 6 | #DEBUG=--no-debug 7 | 8 | # CHOOSE ONE: 9 | # Enabling --release enables compiler optimizations, but makes compilation slower. 10 | RELEASE= 11 | #RELEASE=--release 12 | 13 | SOURCES=$(shell find src/ -type f -name '*.cr') 14 | SPECS=$(shell find spec/ -type f -name '*.cr') 15 | 16 | BUILD_OPTS=${RELEASE} ${DEBUG} --static --verbose --stats --progress --time --threads 8 17 | 18 | out/my_app: $(SOURCES) 19 | mkdir -p /app/out 20 | shards install --frozen 21 | crystal build ${BUILD_OPTS} -o /app/out/my_app src/main.cr 22 | 23 | spec: $(SOURCES) $(TEMPLATES) $(SPECS) 24 | crystal spec --verbose 25 | 26 | clean: 27 | rm -f out/my_app 28 | rm -rf ~/.cache/crystal/ 29 | 30 | .PHONY: all spec clean 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Michael F. Robbins 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # crystal-docker-quickstart 2 | 3 | **crystal-docker-quickstart** provides a project template for quickly working with the [Crystal programming language](https://crystal-lang.org/) in a container, with no installation necessary. 4 | 5 | ## Usage 6 | 7 | 1. (Fork and/or) clone this repository, and give it a name for your project: `git clone https://github.com/compumike/crystal-docker-quickstart.git my_app` 8 | 1. `cd my_app` 9 | 1. Run `./d_dev` to open a bash shell with a Docker container containing this directorye mounted in `/app/` (see source in `/app/src/`, unit tests in `/app/spec/`, and compiled output in `/app/out/`). 10 | 11 | Within the Docker container, you may run: 12 | 13 | ```shell 14 | # To run unit tests: 15 | make spec 16 | 17 | # To rebuild your compiled binary, which lives in /app/out/my_app 18 | make 19 | 20 | # To rebuild the binary, and run it: 21 | make && out/my_app 22 | ``` 23 | 24 | You may edit your source code from another terminal session or your favorite IDE. (The `d_dev` script mounts this directory into the container.) 25 | 26 | Good luck and enjoy! :) 27 | 28 | ## Next Steps 29 | 30 | You may wish to edit some configuration within `Dockerfile`, `d_dev`, or `Makefile`, for example to expose TCP ports, enable compiler release optimizations, or rename your binary to something other than `my_app`. 31 | 32 | If you'd like to incorporate a dependency, known as a "Shard" in the crystal world, first edit `shard.yml`, and then run `shards install` within the Docker container. 33 | 34 | ## Resources 35 | 36 | * [Tutorials](https://crystal-lang.org/reference/1.17/tutorials/basics/index.html) - novice 37 | * [Language Reference](https://crystal-lang.org/reference/1.17/syntax_and_semantics/index.html) - intermediate 38 | * [Standard Library Docs](https://crystal-lang.org/api/1.17.1/) - everyday reference material 39 | * [Docs Home](https://crystal-lang.org/reference/1.17/) 40 | * [Forum](https://forum.crystal-lang.org/) 41 | 42 | ## Supported By 43 | 44 | This work is supported by: 45 | 46 | * [HeyOnCall](https://heyoncall.com/) - [website monitoring](https://heyoncall.com/website-monitoring) and on-call alerting 47 | --------------------------------------------------------------------------------