GitHub Actions: コンテナ上で Step を実行する
docker コマンドで実行する
Docker Hub のイメージを使う場合
普通に docker run すれば良いです。ただし環境変数などは自動では引き継がれないため、必要に応じて指定する必要があります。
    steps:
      - run: docker run -v ${{ github.workspace }}:/work -w /work ubuntu:latest ls -l
カスタムイメージを使う場合
docker build でビルドします。docker-compose でビルドしても良いと思います。
    steps:
      - run: docker build -t test -f ./.github/actions/test/Dockerfile .
      - run: docker run -v ${{ github.workspace }}:/work -w /work test ls -l
カスタムイメージは自動的にはキャッシュされないので、ビルド結果を docker save でファイルに出力してキャッシュすると良さそうです。
    steps:
      - uses: actions/cache@v3
        with: { path: images.tar, key: images }
      - run: |
          if [ -e images.tar ]; then docker image load -i images.tar; fi
          docker build -t test -f ./.github/actions/test/Dockerfile .
          docker image save -o images.tar $(docker image history -q test | egrep '[0-9a-f]+')
      - run: docker run -v ${{ github.workspace }}:/work -w /work test ls -l
Action で実行する
Docker Hub のイメージを使う場合
jobs.<job_id>.steps[*].uses に docker://(イメージ) を指定し、実行するコマンドを entrypoint と args で指定します。entrypoint はフルパスで指定する必要があります。こちらの方法なら適切なオプション付きで docker run が実行されるため、環境変数なども引き継がれます。
    steps:
      - uses: docker://ubuntu:latest
        with: { entrypoint: "", args: ls -l }
複数コマンドを実行したい場合などは、シェルでラップします。(もちろん step を分けても良い。)
    steps:
      - uses: docker://ubuntu:latest
        with:
          entrypoint: ""
          args: |
            bash -c "
              ls -l &&
              ls -l
            "
カスタムイメージを使う場合
何もしない Docker container action を作成し、ローカルアクションとして uses に指定します。Dockerfile で ENTRYPOINT を指定していなければ  entrypoint: "" も不要です。
    steps:
      - uses: ./.github/actions/test/
        with:
          args: ls -l 
以下のように何もしないカスタムアクションを作成する。
- 
.github/actions/test/action.yaml name: Test
 runs:
 using: docker
 image: ./Dockerfile
- 
.github/actions/test/Dockerfile FROM ubuntu:latest
 ...