After writing the code of the project and testing it in a local development environment, you must create a GitLab repository and upload the code and configure to deploy to Heroku.
.gitignore file to your repository so the temporary files and directories generated during the building process don't be uploaded to GitLab. You can use the templates provided by GitLab or generate this file at gitignore.io.
Just type in the search bar the technologies you're using for the project and it will generate the file for you.
The file will look as follows:
# Created by https://www.gitignore.io/api/rust,python # Edit at https://www.gitignore.io/?templates=rust,python ### Python ### # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions *.so # Distribution / packaging .Python build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ wheels/ pip-wheel-metadata/ share/python-wheels/ *.egg-info/ .installed.cfg *.egg MANIFEST # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .nox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *.cover .hypothesis/ .pytest_cache/ # Translations *.mo *.pot # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ # PyBuilder target/ # pyenv .python-version # pipenv # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. # However, in case of collaboration, if having platform-specific dependencies or dependencies # having no cross-platform support, pipenv may install dependencies that don't work, or not # install all needed dependencies. #Pipfile.lock # celery beat schedule file celerybeat-schedule # SageMath parsed files *.sage.py # Spyder project settings .spyderproject .spyproject # Rope project settings .ropeproject # Mr Developer .mr.developer.cfg .project .pydevproject # mkdocs documentation /site # mypy .mypy_cache/ .dmypy.json dmypy.json # Pyre type checker .pyre/ ### Rust ### # Generated by Cargo # will have compiled files and executables /target/ # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html Cargo.lock # These are backup files generated by rustfmt **/*.rs.bk # End of https://www.gitignore.io/api/rust,python
Go to dashboard.heroku.com/account and copy the API Key.
Create a new Dockerfile in your repository. it will have the following content:
FROM docker.io/username/rust-python:latest WORKDIR /home/admin USER admin RUN mkdir app WORKDIR app RUN env PYTHON_CONFIGURE_OPTS='--enable-shared' pyenv install 3.7.7 ENV LD_LIBRARY_PATH $HOME/.pyenv/versions/3.7.7/lib/ RUN pyenv global 3.7.7 RUN pyenv rehash RUN rustup override set nightly COPY pyproject.toml ./ RUN poetry config virtualenvs.create false \ && poetry lock \ && poetry export --without-hashes -f requirements.txt --dev \ | poetry run pip install -r /dev/stdin \ && poetry debug COPY . ./ RUN poetry install --no-interaction \ && cargo build --release CMD ["sh", "run"]
According to this issue, the container registry address (docker.io) must be specified before the name of the base image, for buildah to pull the image correctly from Docker Hub.
The base image used for the project will be the one created before and available from
Then set the
/home/admin and the
admin. Create the
app directory and set it as
Install Python 3.7.7 with shared libraries and set the
LD_LIBRARY_PATH environment variable.
Specify the version of Python and Rust to be used.
pyproject.toml file. Poetry is being used to manage the dependencies of Python but no virtual environment will be created.
Then lock the dependencies and export to a
requirements.txt file and install them using
pip, this is done to generate a cache of them.
Then install Python and Rust dependencies of the project, and build the project for production.
When the Docker image being created is run, the bash script named
run is executed.
run bash script has the following content, so that Heroku knows how to run the app:
ROCKET_PORT=$PORT ROCKET_ENV=prod ./target/release/rust-python-demo
$PORT is set by Heroku as it dynamically chooses a port for the app, this value is assigned to
ROCKET_PORT. Then the environment is set to production with
ROCKET_ENV=prod and the binary of the app is run.
Add the value of the API Key of Heroku that you copied before to the settings of the repository by following the steps bellow:
- Go to
- In the
Variablessection click on
- Add the variable
HEROKU_API_KEYand assign the value copied before.
Then add the
.gitlab-ci.yml file, this is the configuration file of the Continuous Integration system provided by GitLab.
For this I just follow Alessandro Diaferia's tutorial on Continuous Deployment With GitLab, Docker And Heroku.
The file will look as follows:
stages: - build - release build_image: only: - master image: registry.gitlab.com/majorhayden/container-buildah stage: build variables: STORAGE_DRIVER: "vfs" BUILDAH_FORMAT: "docker" before_script: - dnf install -y nodejs - curl https://cli-assets.heroku.com/install.sh | sh - sed -i '/^mountopt =.*/d' /etc/containers/storage.conf script: - buildah bud --iidfile iidfile -t rust-python-demo:$CI_COMMIT_SHORT_SHA . - buildah push --creds=_:$(heroku auth:token) $(cat iidfile) registry.heroku.com/heroku-app-name /web release: only: - master image: node:10.17-alpine stage: release before_script: - apk add curl bash - curl https://cli-assets.heroku.com/install.sh | sh script: - heroku container:release -a heroku-app-name web
It will only have two stages,
build_image, where the Docker image is built using the Dockerfile created previously and added to the registry of Heroku, and
release, where the image will be pushed to the Heroku app.
heroku container:release -a heroku-app-name web with the name of the app you created on Heroku.
You can go to rust-python-demo.herokuapp.com to see a live demo running.